I must immediately warn that this topic is hardly useful to programmers who are friends with C ++ for a long time and firmly. My goal is to help those who, when using other people's libraries with a large number of template, fall into a slight panic at the sight of error messages. As practice shows, often everything is not at all as scary as it looks and quite helps to understand what the problem is.
The idea to write a similar note arose in the process of writing a program that actively uses Boost :: Spirit2 - a complex grammar, an abundance of semantic action, the creation of an AST through an attribute value and so on. At some point I noticed that one or two minutes would be enough for me to correct many errors, while at the beginning of work on a project in similar cases, it could take up to an hour to analyze the situation.
Everything is written on the basis of working with gcc, but I think it will not be difficult to draw an analogy with the% compiler_name used &. ')
It's time to share!
What will help us?
Fatal errors
First of all, it is worthwhile to include the compiler option that makes any mistake fatal. In the case of gcc, this is -Wfatal-errors . In the case of metaprogramming, the study of more than one error message at a time still does not make much sense - most likely the correction of the first one will also affect many subsequent ones. And the wall of the text will be much lower.
To root
If you look closely, it turns out that the template error messages have approximately the following structure:
In file included from %header path%, from %header path%, ... from %source filename%: %header path%: In function '%full name%' %header path%: instantiated from '%full name%' ... %source filename%: instantiated from %full name% ... %header path%: error: %error description%
And if you take a closer look, it turns out that the block with “instantiated from” passing through the entire hierarchy of included header files is the most voluminous and the most useless. We are hardly often interested in what devious ways it came from calling a library function to an error. But it is interesting what kind of error it is and exactly which line of our code (the “instantiated from” block for% source filename%) generated it.
And this is quite a bit and quite readable. Sometimes it is enough just to look at the line in the code, because of which everything has gone and the most stupid typo immediately becomes visible, resulting in similar indecency. You do not even have to read the error message, which in such a situation would still not say anything sensible.
typedef is typedef
It is convenient to have on hand a set of find-and-replace rules for basic typedef types used in the problem code. Even a short std :: basic_string <char> looks much better in the form of std :: string , let alone talk about the vectors of lists of pairs of vectors and queues. For example, in vim, you can write a simple replace-script through which to run an error message each time, if it is longer than a couple of lines, and lead to a readable form.
Reading sources
If the error is in the template code, then we are almost a step away from the sources. When there is not even the slightest idea what the problem may be, you should open that part of the library header file that the compiler complains about (% header path%: error :) and get to know it better. As a rule, even in very cruel boost libraries small pieces are readable and understandable separately.
After I stopped looking at the next error message in horror, and immediately began to dissect in these simple ways, the debugging time was reduced by an order of magnitude. What you want.
What tricks do you use? I would be glad to read in the comments tips on the topic. I propose to deal with the drawbacks of C ++ design collectively.