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();
}
5. Which keyword is used for the template? Explanation: C++ uses template reserved keyword for defining templates.
" typename " is a keyword in the C++ programming language used when writing templates. It is used for specifying that a dependent name in a template definition or declaration is a type.
When you call a function template, the compiler tries to deduce the template type. Most of the time it can do that successfully, but every once in a while you may want to help the compiler deduce the right type — either because it cannot deduce the type at all, or perhaps because it would deduce the wrong type.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With