哪个编译器是对的?需要模板化返回类型之前的'模板'吗?

时间:2011-06-03 20:26:04

标签: c++ templates visual-c++ g++ correctness

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;
}

1 个答案:

答案 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?