我正在尝试使用g ++编译一些Microsoft Visual C ++代码。现在我遇到了一个我真的无法理解的编译器错误。 (简化)代码如下所示:
template<int X> struct A {
template<class Ret> static Ret call() {
return 0;
}
};
template<int X> struct B : A<X> {
int f() {
return A<X>::call<int>();
}
};
当我尝试用g ++(版本4.4.5)编译它时,我收到以下错误:
main.cpp: In member function int B<X>::f():
main.cpp:16: error: expected primary-expression before int
main.cpp:16: error: expected ; before int
main.cpp:16: error: expected unqualified-id before > token
如果我从方法A :: call中删除模板类型(Ret),则代码编译得很好。任何人都可以在这看到错误吗?
谢谢!
答案 0 :(得分:5)
您需要template
关键字:
return A<X>::template call<int>();
call
是一个从属名称,这意味着它的含义取决于模板参数,当编译器处理f()
时,该参数是未知的。您需要通过在call
关键字前添加前缀来表明template
是一个功能模板。
当您尝试访问嵌套类型时会发生同样的情况:您需要添加typename
关键字以指示名称表示类型:
template <typename T>
struct A { typedef int type; };
template <typename T>
void f()
{
typename A<T>::type i = 0; // notice "typename" here
}
有时你甚至需要混合两者:
template <typename T>
struct A
{
template <typename U>
struct inner { };
};
template <typename T>
void f()
{
typename A<T>::template inner<int> var;
}
在这个问题的答案中详细解释了这两个关键字的使用:Where and why do I have to put the “template” and “typename” keywords?(感谢@BjörnPollex找到链接)。
答案 1 :(得分:5)
A
是一个模板,在不知道X
的情况下,编译器无法确定A<X>
的内容。特别是它不知道call
最终会成为模板。
要告诉编译器,您必须使用template
关键字:
template<int X> struct B : A<X> {
int f() {
return A<X>::template call<int>();
}
};
答案 2 :(得分:3)
您必须指定您正在调用的函数是模板,因为它是模板类的一部分。编译器不知道任何给定的A<X>
都有一个名为call
的模板函数,因此您需要帮助它。
template<int X> struct B : A<X> {
int f() {
return A<X>::template call<int>();
}
};