我有这段代码,它没有编译(编辑:在 VC 中编译,但不是在 GCC 中编译):
template<int N>
struct List
{
template <class C>
void clear() { }
};
template <int L>
class Test
{
public:
List<L> list; // <--This line
void method()
{
list.clear<int>(); // <-- Compile error here: error: expected primary-expression before ‘int’
}
};
我怎样才能让它发挥作用?编译器 (gcc) 似乎不理解上下文,因为如果在标记行中我用数字替换 L,如 List<1> list;
然后编译正常。
当您使用 Test
模板参数实例化 List
时,它变成了一个依赖模板。编译器在解析 Test
时无法实例化它,因为它还不知道 L
的值,而且它只知道 List
可能是特化的L
的不同值不同。所以编译器不能确定 clear
是一个模板并且会混淆。您必须添加 template
关键字来消除歧义,例如:
list.template clear<int>();
// ^^^^^^^^ here just before the dependent template
当您将 L
替换为 1
时,模板不再依赖于封闭模板的参数,因此编译器实例化并看到 clear
是一个模板,不需要消歧。
依赖模板的所有成员都需要消除歧义。编译器总是假定它们是值(函数或数据),因此类型必须用 typename
和模板用 template
来消除歧义。
template
关键字的使用是规范的一部分。 MSVC 可以解析很多情况,包括这个,没有它,但它是 MSVC 扩展。 Gcc 在此处要求 template
关键字是正确的。
参见 this answer进行详尽的讨论。