哪个编译器是正确的? 'template'在需要模板化返回类型之前?

Which compiler is right? 'template' before templated return type needed?

本文关键字:返回类型 编译器 template      更新时间:2023-10-16

这个片段(取自这个问题)用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;
}

GCC是对的。AttributeType是一个从属模板名称,后面跟有尖括号<,因此这里需要关键字template来消除歧义1,使编译器清楚地知道后面是一个模板名称。§14.2/4:中提到了该规则

当成员模板的名称专业化出现在之后。或->在后缀表达式中,或在中的嵌套名称说明符合格的id,以及后缀表达式或限定id显式依赖于模板参数(14.6.2)成员模板名称必须加前缀通过关键字模板。否则name被假定为非模板。

1@Johannes在这里写了一个非常好的解释:

我必须把";模板";以及";typename";关键词?