views:

638

answers:

8

I find it very hard to figure out what is wrong with my code when using C++ template meta-programming. It might be that I am just not very good at understanding the error messages, but as far as I'm aware I can't resort to putting in print statements or breakpoints to figure out what's going on.

What tips or advice can you offer when trying to figure out why something is not compiling other than just picking through the code manually and hoping it will come to me?

+4  A: 

You can try using a newer compiler. If you're using Visual C++ 6.0, switch to 9.0 and you'll see a huge jump in the helpfulness of the compiler errors.

Otherwise, my techniques are usually been to test out as small a section of code as possible until I get the errors isolated. This is probably the template system's greatest failing - there is no sensible way of debugging them.

In you're own code, make liberal use of compile-time asserts to make usage problems a little easier to diagnose.

Eclipse
You can use compile time asserts without boost also. Details here:http://www.pixelbeat.org/programming/gcc/static_assert.html
pixelbeat
In a corporate environment you might not be able to migrate away from VC6.
graham.reeds
graham: A company that still forces its employees to use VC6 is a company I don't want to work for, ever, under no circumstances. Giving you such inappropriate tools shows very clearly that the company just doesn't care about you. Not a healthy relationship.
Konrad Rudolph
+10  A: 

For the STL at least there are tools available that will output more human-friendly error messages. See http://www.bdsoft.com/tools/stlfilt.html

For non-STL templates you'll just have to learn what the errors mean. After you've seen them a dozen times it becomes easier to guess what the problem is. If you post them here maybe somebody can help you figure it out.

Michel
Darn, you beat me to the punch by 37 seconds.
James Matta
Great minds think alike
Michel
Here I'll give you a pity point
Michel
+3  A: 

This should help you I think.

http://www.bdsoft.com/tools/stlfilt.html

I have not used it myself; but, it might help you. I can also tell you that as you get more experience with templates and metaprograms you will get used to the error messages. They can be a bit tough to read sometimes; but, there is logic to their madness. Just make your terminal as large as you can and try to translate what it is saying in your head as you read it.

James Matta
+3  A: 

Which compiler are you using? VC8 and 9 are actually pretty decent at outputting readable error messages. It still takes a bit of patience to go through, but it can be done, and they essentially show the compile-time equivalent of the call stack. Starting at the bottom, which template instantiation caused the error, and what were the template arguments? Next level up shows the template it was instantiated from and so on, all the way up to the top-level. Of course this is only visible in the "output" tab, not the "errors" one which it normally shows after a failed compile.

The principle is similar in GCC, although last I tried, at least, the formatting was somewhat less readable. But really, you just have to trace through the stack of instantiations, and at each level, verify that it got instantiated with the types you expected, until you find the one that introduced the error.

It's a pain, but it can be done, and it requires nothing more than patience and a willingness to read the error messages. :)

Also, liberal use of static_assert (or BOOST_STATIC_ASSERT) can help a lot by providing sanity checks

jalf
+2  A: 

You get used to it as time goes by, and unfortunately if you plan on using C++, you have to. Because, some libraries like VC9 have good error messages, but as soon as you move to say GCC, or some other compiler, the messages are gone. And even VC9 won't help you much when you have errors from some library written by someone else, or yourself during a late-night, even some Boost libraries aren't that friendly. Simply because not every author has taken the trouble to make things clear when an error occurs, and that is even more common with new libraries (that tend to have the most errors and less help).

Also you must remember that the nice STATIC_ERRORS you may find here and there in code, are placed by the authors where things commonly break, and there will always be horrible corner cases, that the author didn't contemplate, that will produce 400 lines of error messages because you missed a const somewhere for example.

Using tools will help you out in the beginning, but hurt you on the long run. And since the problem is inherent of C++, its not going away any day soon. And these walls of errors will likely be with us until C++ is no longer in use. So tools will just cut your teeth, when you need them to survive. If you planning on leaving C++ soon, then please feel free to use them. Nowadays I can normally understand those 400-line error messages in one glance, so they are crystal clear to my eyes, but thats not thanks to any tools.

As with everything, especially C++, it takes experience and training.

Robert Gould
+2  A: 

If you're using gcc, I've found that colorgcc can help out a tiny bit. The color coding makes it easier to mentally parse out warnings vs. errors vs. contextual information.

Mr Fooz
+3  A: 

When making something complicated in meta-programming language, i use the BOOST_MPL_ASSERT macro multiple times, checking the results of every step of the meta-execution. The Boost.MPL library is very useful for that matter. I suggest you use as much code from there as possible, because it's likely it won't contain errors.

When i am not so sure the right specialization for a class is being used, i tend to isolate the right specialization in a namespace. Once you are sure that specialization is valid, you have to make sure that it is chosen. If it's not, you have to find out which one is chosen in its place. Then i'd recommend using Boost.EnableIf to exclude this wrongly-accepted specialization from the selection process.

Last but not least, STLfilt is extremely useful, and you can modify it yourself so that it suits your needs as well as possible.

But the most important thing is to try not to use meta-programming everywhere. It is complicated, so use it only when you really need it.

Benoît
+2  A: 

As the answers already illustrate, there are basically 2 types of difficulties in template code: 1. getting it to compile, and find the cause for compiler errors 2. getting it do do the right thing during runtime

I usually try to separate compile time type magic from run time logic, this helps with finding the cause of the problem (Type 1 or 2). A way to achieve this is to use one template type for type magic, and as little as possible run-time functionality, and one plain type for run-time logic, that uses the template type.

If you then follow the advices from the other replies, especially the one about compile_time asserts, it will be easier to find the source of trouble.

tabdamage