Reputation: 4530
This question is related to my previous question Compiler error when trying to call template method from private instance, which was pointed out to be related to this question: Where and why do I have to put the "template" and "typename" keywords?
So I read this and I get the idea that the C++ language definition is ambiguous so it cannot always be parsed correctly. In my case, the answer was that I need a.template f<1>()
in B::test()
to help the parser understand that it is dealing with a template. Fine.
But, after reading all this, why the heck is the parser suddenly able to do without the template
keyword if I happen to have a completely unrelated global template function that happens to have the same name? This compiles without problems and behaves as expected:
#include <iostream>
template <int i>
void f() {std::cout << "f()\n";}
template <int N>
struct A {
template <int i>
void f() {std::cout << "A::f()\n";}
};
template <int N>
struct B {
A<N> a;
B(A<N>& a) : a(a) {}
void test() {
f<1>();
a.f<1>(); // compiles without 'template' keyword!
}
};
int main() {
A<2> a;
a.f<1>(); // works fine
B<2> b(a);
b.test();
}
I found that the global function must:
f
B
Otherwise, it can be pretty much anything. So
template <typename T, unsigned k>
void *f(double x, const char *s) {return NULL;}
works just as well to help the parser out that a.f<1>()
in B::test()
is in fact to be parsed as a.template f<1>()
.
What is the compiler thinking? Like: "Well, the guy already has a global template function called f<>()
, so when I'm parsing this completely unrelated expression a.f<1>()
inside B::test()
, I'm going to assume that it's also a template function?" What is this?
What did I miss when reading Where and why do I have to put the "template" and "typename" keywords??
Update
The code above compiles for me with all of:
I also tested with the compiler flags -pedantic -Wall -Wextra
and with -std=c++11
for g++-4.8
. It worked in all cases.
Update 2
This also works without template
keyword:
// ...
template <int N, template <int> class A>
struct B {
A<N> a;
B(A<N>& a) : a(a) {}
void test() {
f<1>();
a.f<1>(); // compiles without 'template' keyword!
}
};
int main() {
A<2> a;
a.f<1>(); // works fine
B<2, A> b(a);
b.test();
}
Upvotes: 7
Views: 375
Reputation: 56557
I think g++
is correct and the code should compile without .template
. According to the standard (at least up to my understanding),
3.4.5/1 (page 55 of N3936)
In a class member access expression (5.2.5), if the . or -> token is immediately followed by an identifier followed by a <, the identifier must be looked up to determine whether the < is the beginning of a template argument list (14.2) or a less-than operator. The identifier is first looked up in the class of the object expression. If the identifier is not found, it is then looked up in the context of the entire postfix-expression and shall name a class template.
Upvotes: 2