此问题与我之前提出的问题Compiler error when trying to call template method from private instance有关,该问题被指出与此问题有关:Where and why do I have to put the "template" and "typename" keywords?
所以我读了这篇文章,并且我认为C ++语言定义含糊不清,所以不能总是正确解析它。就我而言,答案是我需要a.template f<1>()
中的B::test()
来帮助解析器理解它正在处理模板。细
但是,在阅读了所有这些之后,如果碰巧有一个完全不相关的全局模板函数碰巧具有相同的名称,为什么解析器突然能够在没有template
关键字的情况下完成?这可以毫无问题地编译并且按预期运行:
#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();
}
我发现全局函数必须:
f
B
否则,它几乎可以是任何东西。所以
template <typename T, unsigned k>
void *f(double x, const char *s) {return NULL;}
也可以帮助解析器,a.f<1>()
中的B::test()
实际上被解析为a.template f<1>()
。
编译器在想什么?喜欢:“嗯,这家伙已经有一个名为f<>()
的全局模板函数,所以当我在a.f<1>()
内解析这个完全不相关的表达式B::test()
时,我会假设它是还有模板功能吗?“这是什么?
阅读Where and why do I have to put the "template" and "typename" keywords?时我错过了什么?
更新
上面的代码为我编译所有:
我还使用编译器标志-pedantic -Wall -Wextra
和-std=c++11
测试g++-4.8
。它适用于所有情况。
更新2
这也可以在没有template
关键字的情况下使用:
// ...
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();
}
答案 0 :(得分:2)
我认为g++
是正确的,代码应该在没有.template
的情况下编译。根据标准(至少根据我的理解),
3.4.5 / 1 (N3936第55页)
在类成员访问表达式(5.2.5)中,如果是。或 - &gt;令牌后面紧跟着一个标识符,后跟一个&lt ;,必须查找标识符以确定&lt;是模板参数列表(14.2)或小于运算符的开头。首先在对象表达式的类中查找标识符。如果找不到标识符,则在整个postfix-expression的上下文中查找它,并命名一个类模板。