jalone jalone - 1 month ago 9
C++ Question

How to deal with way too long STL template error report?

When programming in c++ STL, or intensively using 'templatization', and some compiling error happens, often the error report is really long, and often too much not needed information is given.
I'm talking about gcc, i don't know if with other compilers is different, but some times even for just a typo, it takes a while to catch the error purging the

<ns::type<ns::type<ns::type, ns::type<...><ns::type<...> > > > >


I'm looking for some compiler flag, trick, workaround or methodology ( i currently copy past the error and put on two lines what i have and what compiler use to want and removing variables bookmarks... (kinda sad procedure for a not-so-uncommon ctrl+s non well performed)) that could make this task quicker or just helping me ( even only some IDE error syntax highlight... )

Answer

STLFilt: An STL Error Message Decryptor for C++ is a popular tool to filter these verbose error messages and turn them into something more legible.

From their website:

STLFilt was initially conceived as a teaching aid, to allow students taking C++ and/or STL-specific workshops to make sense of typically overbloated STL error messages. Today, however, even some C++ experts have adopted STLFilt for use in everyday development. The results may not always be perfect, but most of the time the information lost during Decryption is not critical to the application being debugged. The rest of the time, Decryption is easy enough to bypass.

The distribution for each platform (compiler/library set) is self-contained and tuned to the idiosyncrasies of that platform. Each Perl script performs basic regex substitutions for all the standard (and extended, if present in the library) STL components, while certain versions of the script go further with respect to message ordering, line wrapping, library header error treatment, etc., as I unilaterally deemed appropriate for that platform.

Here's a demo run that shows how it can be useful:

The source program:

#include <map>
#include <algorithm>
#include <cmath>

const int values[] = { 1,2,3,4,5 };
const int NVALS = sizeof values / sizeof (int);

int main()
{
    using namespace std;

    typedef map<int, double> valmap;

    valmap m;

    for (int i = 0; i < NVALS; i++)
        m.insert(make_pair(values[i], pow(values[i], .5)));

    valmap::iterator it = 100;              // error
    valmap::iterator it2(100);              // error
    m.insert(1,2);                          // error

    return 0;
}

First, an unfiltered run using the MinGW gcc 3.2 compiler:

d:\src\cl\demo>c++2 rtmap.cpp
rtmap.cpp: In function `int main()':
rtmap.cpp:19: invalid conversion from `int' to `
   std::_Rb_tree_node<std::pair<const int, double> >*'
rtmap.cpp:19:   initializing argument 1 of `std::_Rb_tree_iterator<_Val, _Ref,
   _Ptr>::_Rb_tree_iterator(std::_Rb_tree_node<_Val>*) [with _Val =
   std::pair<const int, double>, _Ref = std::pair<const int, double>&, _Ptr =
   std::pair<const int, double>*]'
rtmap.cpp:20: invalid conversion from `int' to `
   std::_Rb_tree_node<std::pair<const int, double> >*'
rtmap.cpp:20:   initializing argument 1 of `std::_Rb_tree_iterator<_Val, _Ref,
   _Ptr>::_Rb_tree_iterator(std::_Rb_tree_node<_Val>*) [with _Val =
   std::pair<const int, double>, _Ref = std::pair<const int, double>&, _Ptr =
   std::pair<const int, double>*]'
E:/GCC3/include/c++/3.2/bits/stl_tree.h: In member function `void
   std::_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::insert_unique(_II,

   _II) [with _InputIterator = int, _Key = int, _Val = std::pair<const int,
   double>, _KeyOfValue = std::_Select1st<std::pair<const int, double> >,
   _Compare = std::less<int>, _Alloc = std::allocator<std::pair<const int,
   double> >]':
E:/GCC3/include/c++/3.2/bits/stl_map.h:272:   instantiated from `void std::map<_
Key, _Tp, _Compare, _Alloc>::insert(_InputIterator, _InputIterator) [with _Input
Iterator = int, _Key = int, _Tp = double, _Compare = std::less<int>, _Alloc = st
d::allocator<std::pair<const int, double> >]'
rtmap.cpp:21:   instantiated from here
E:/GCC3/include/c++/3.2/bits/stl_tree.h:1161: invalid type argument of `unary *
   '

And a filtered run using the gcc-specific Proxy c++:

d:\src\cl\demo>c++ rtmap.cpp
  *** {BD Software Proxy c++ for gcc v3.01} STL Message Decryption is ON! ***
rtmap.cpp: In function `int main()':
rtmap.cpp:19: invalid conversion from `int' to `iter'
rtmap.cpp:19:   initializing argument 1 of `iter(iter)'
rtmap.cpp:20: invalid conversion from `int' to `iter'
rtmap.cpp:20:   initializing argument 1 of `iter(iter)'
stl_tree.h: In member function `void map<int,double>::insert_unique(_II, _II)':
    [STL Decryptor: Suppressed 1 more STL standard header message]
rtmap.cpp:21:   instantiated from here
stl_tree.h:1161: invalid type argument of `unary *'

STL Decryptor reminder:
    Use the /hdr:L option to see all suppressed standard lib headers

[Note: demo runs were performed in an 80-column console window with STLFilt's intelligent line wrapping enabled, and with internal switches set to produce messages as terse as possible. More detail is available by tailoring the Decryptor's options.]

The only downside I can see is that it mislabels the C++ Standard Library. :(

Here's a relevant journal article by STLFilt's author.

Comments