Error messages + templates: some simple tips

    A bit of lyrics

    I must immediately warn that this topic is unlikely to be useful to programmers who have been friends with C ++ for a long time and are strong. My goal is to help a little those who, when using other people's libraries with a large number of templates, fall into a slight panic when they see error messages. As practice shows, often everything is not so scary as it looks and it helps to understand what the problem is.

    The idea to write such a note arose in the process of writing a program that actively uses Boost :: Spirit2 - a complex grammar, an abundance of semantic action, creating an AST via attribute value and the like. At some point, I noticed that it took me one or two minutes to fix many errors, while at the beginning of work on the project in similar cases it could take up to an hour to analyze the situation.

    Everything is written based on work with gcc, but I think it will not be difficult to draw an analogy with the used% compiler_name &.

    It's time to share!

    What will help us?

    • Fatal errors

      First of all, you should enable the compiler option, which makes any error fatal. In the case of gcc, these are -Wfatal-errors . In the case of metaprogramming, studying more than one error message at a time still does not make much sense - most likely, fixing the first of them will affect a lot of subsequent ones. And the wall of the text will be much lower.

    • 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 look closely, it turns out that the “instantiated from” block, which goes through the entire hierarchy of included header files, is the most voluminous and most useless. We are hardly often interested in what roundabout ways it came from calling a library function to an error. But she is interested in what kind of error it is and which particular line of our code (the “instantiated from” block for% source filename%) generated it.

      And this is quite a bit and quite readable. Sometimes it’s enough just to look at the line in the code, because of which everything started to go away and immediately you see the stupid typo, resulting in such indecency. You don’t even have to read the error message, which in such a situation will still not say anything sensible.

    • typedef is typedef

      It is convenient to have at hand a set of find-and-replace rules for the basic typedef types used in the problematic code. Even a short std :: basic_stringit looks much better in the form of std :: string , to say nothing of 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 every time, if it is longer than a couple of lines, and make it readable.

    • Reading source

      If there is an error in the template code, then we are almost a step away from the source. When there is no idea what the problem may be, it is worth opening the part of the library header file that the compiler complains about (% header path%: error:) and get to know better. As a rule, even in very cruel boost libraries, small pieces are individually readable and understandable.

    After I stopped looking in horror at the next error message, and began to dissect immediately with these simple methods, the debugging time was reduced by an order of magnitude. Which I wish you too.

    What tricks do you use? I would be glad to read tips on the topic in the comments. I propose to deal with the design flaws of C ++ collectively.

    Also popular now: