This snippet(取自this question)用g ++编译好(如图所示),返回类型之前的template
就行了。相反,VC10不会使用以下错误编译该代码:
错误C2244:'A :: getAttr':无法将函数定义与现有声明匹配
如果删除template
,VC10很高兴,但g ++会尖叫这个错误:
错误:非模板'AttributeType'用作模板
注意:使用'A :: template AttributeType'表示它是模板
是否因为VC的两相查找失败或原因是什么?哪个编译器就在这里?我怀疑g ++是正确的,因为我在这里需要template
的模糊记忆,就像分配器中的rebind
模板一样。
编辑:我们有一个胜利者:g ++ / GCC(惊喜......)。
template <typename T, typename K>
class A {
public:
T t;
K k;
template <int i, int unused = 0>
struct AttributeType{
};
template <int i>
AttributeType<i> getAttr();
};
template <typename T, typename K>
template <int i>
typename A<T, K>::template AttributeType<i> A<T, K>::getAttr() {
// ^^^^^^^^ -- needed or not?
return t;
}
int main(){
A<int,int> a;
}
答案 0 :(得分:10)
AttributeType
是依赖的模板名称,后跟尖括号<
,因此此处需要关键字template
以消除歧义 1 ,使其清晰在编译器中,所遵循的是模板名称。该规则在§14.2/ 4中提及:
当成员模板的名称时 专业化之后出现。或 - &gt; 在后缀表达式中,或之后 a中的嵌套名称说明符 qual-id和 postfix-expression或qualified-id 明确取决于a template-parameter(14.6.2),. 成员模板名称必须加前缀 通过关键字模板。否则 假定名称命名为 非模板。
1 @Johannes在这里写了一个非常好的解释:
Where and why do I have to put the "template" and "typename" keywords?