I know this may not be as helpful as you wanted, but I've found the best tool against template error messages is knowledge.
A good understanding of the STL and how to use it will help you avoid lots of errors in the first place. Secondly, often error messages refer to functions in the STL source - if you have a rough idea how the STL is implemented, this can be extremely helpful in deciphering what the error message is going on about. Finally, compiler makers are aware of this issue and are gradually improving error message output, so you would do well to stick to the latest version of your compiler.
Here's a good example of an obscure template error:
std::vector<std::unique_ptr<int>> foo;
std::vector<std::unique_ptr<int>> bar = foo;
unique_ptr
is not copyable, it can only be moved. So trying to assign a vector of unique_ptr to another vector will mean somewhere in the vector source code will try to copy a unique pointer. Therefore the error will originate from code which is not yours and throw a fairly opaque error message as a result. The ideal error message would be
main.cpp(20): cannot construct 'bar' from 'foo': foo's template type is non-copyable
Instead, VS2010 gives the following error:
1>C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\xmemory(48): error C2248: 'std::unique_ptr<_Ty>::unique_ptr' : cannot access private member declared in class 'std::unique_ptr<_Ty>'
1> with
1> [
1> _Ty=int
1> ]
1> C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\memory(2347) : see declaration of 'std::unique_ptr<_Ty>::unique_ptr'
1> with
1> [
1> _Ty=int
1> ]
1> C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\xmemory(197) : see reference to function template instantiation 'void std::_Construct<std::unique_ptr<_Ty>,const std::unique_ptr<_Ty>&>(_Ty1 *,_Ty2)' being compiled
1> with
1> [
1> _Ty=int,
1> _Ty1=std::unique_ptr<int>,
1> _Ty2=const std::unique_ptr<int> &
1> ]
1> C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\xmemory(196) : while compiling class template member function 'void std::allocator<_Ty>::construct(std::unique_ptr<int> *,const _Ty &)'
1> with
1> [
1> _Ty=std::unique_ptr<int>
1> ]
1> C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\vector(421) : see reference to class template instantiation 'std::allocator<_Ty>' being compiled
1> with
1> [
1> _Ty=std::unique_ptr<int>
1> ]
1> C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\vector(481) : see reference to class template instantiation 'std::_Vector_val<_Ty,_Alloc>' being compiled
1> with
1> [
1> _Ty=std::unique_ptr<int>,
1> _Alloc=std::allocator<std::unique_ptr<int>>
1> ]
1> main.cpp(19) : see reference to class template instantiation 'std::vector<_Ty>' being compiled
1> with
1> [
1> _Ty=std::unique_ptr<int>
1> ]
Sifting through this there are clues. The first section references a private member access of std::unique_ptr<int>
. The second section, if you click through to the source line, points at the copy constructor of unique_ptr
, which is declared beneath a private:
specifier. So now we know we tried to copy a unique_ptr which is not allowed. Sections 3, 4 and 5 just point to boilerplate code - it's just noise. Section 6 says "see reference to class template instantiation 'std::_Vector_val<_Ty,_Alloc>' being compiled". In other words, this error happened in vector's template code. The last section is most interesting: it directly points at the line declaring foo
in your own source code - it's figured out where in your own source code the error originated from!
So adding up the clues:
- It originates in foo,
- It originates in vector code,
- It tries to copy a unique_ptr which is not allowed.
- Conclusion: the vector tried to copy one of its elements, which is not allowed. Review code for
foo
and check for anything causing a copy.
Since the compiler only pointed at foo's declaration, if the assignment is far away in the source code some hunting will be involved. This obviously is not ideal, but I think this approach ultimately gives you more chance of fixing mistakes in general. You'll start to recognise that kind of error dump means "you copied a unique_ptr". Again, I'm not defending it, it definitely needs improving - but I think these days there's just enough information in the output that combined with a good knowledge of the STL allows you to fix the problem.