I've been playing with clang a while, and I stumbled upon "test/SemaTemplate/dependent-template-recover.cpp" (in the clang distribution) which is supposed to provide hints to recover from a template error.
The whole thing can be easily stripped down to a minimal example:
template<typename T, typename U, int N> struct X {
void f(T* t)
{
// expected-error{{use 'template' keyword to treat 'f0' as a dependent template name}}
t->f0<U>();
}
};
The error message yielded by clang:
tpl.cpp:6:13: error: use 'template' keyword to treat 'f0' as a dependent template name
t->f0<U>();
^
template
1 error generated.
... But I have a hard time understanding where exactly one is supposed to insert the template
keyword to have the code to be syntactically correct?
Insert it just before the point where the caret is:
Edit: the reason for this rule becomes clearer if you think like a compiler.
Compilers generally only look ahead one or two tokens at once, and don't generally "look ahead" to the rest of the expression.[Edit: see comment] The reason for the keyword is the same as why you need thetypename
keyword to indicate dependent type names: it's telling the compiler "hey, the identifier you're about to see is the name of a template, rather than the name of a static data member followed by a less-than sign".Excerpt from C++ Templates
The .template Construct A very similar problem was discovered after the introduction of typename. Consider the following example using the standard bitset type:
The strange construct in this example is .template. Without that extra use of template, the compiler does not know that the less-than token (<) that follows is not really "less than" but the beginning of a template argument list. Note that this is a problem only if the construct before the period depends on a template parameter. In our example, the parameter bs depends on the template parameter N.
In conclusion, the .template notation (and similar notations such as ->template) should be used only inside templates and only if they follow something that depends on a template parameter.
In addition to the points others made, notice that sometimes the compiler couldn't make up his mind and both interpretations can yield alternative valid programs when instantiating
This prints
0
when omittingtemplate
beforef<int()>
but1
when inserting it. I leave it as an exercise to figure out what the code does.ISO C++03 14.2/4:
In
t->f0<U>();
f0<U>
is a member template specialization which appears after->
and which explicitly depends on template parameterU
, so the member template specialization must be prefixed bytemplate
keyword.So change
t->f0<U>()
tot->template f0<U>()
.