Notice that there are code snippet that are valid for both the keyword added and not added, yielding different results in each case, even for templates that take type parameters instead of integers.
#include <iostream>
struct A {
template<typename T>
static A f(T) {
return A();
}
template<typename T> operator T() { return T(); }
};
template<typename U>
int g() {
U u;
typedef A (*funcPtrType)(int());
return !(funcPtrType)u.f < int() > (0);
}
int main() {
std::cout << g<A>() << std::endl;
}
This outputs 0
when run without the template
keyword added. If you add the keyword before f < int() >
it outputs 1
.
Explanation
The version without the keyword parses as
funcPtrType temp1 = (funcPtrType)u.f; // taking func address
bool temp2 = !temp1; // temp2 == false
bool temp3 = temp2 < int(); // temp3 == false
bool temp4 = temp3 > (0); // temp4 == false
return temp4;
And the version with the keyword parses as
A temp1 = u.template f < int() > (0); // function call
funcPtrType temp2 = (funcPtrType) temp1; // temp2 == 0
bool temp3 = !temp2; // temp3 == true
return temp3;
Notice that temp2
is a null pointer (produced by return T()
). Whole different parses, and both are valid! This really needs a way to disambiguate - which is to insert the template
keyword as appropriate.