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

Xeo*_*Xeo 15 c++ templates correctness g++ visual-c++

这段代码(取自这个问题)用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;
}
Run Code Online (Sandbox Code Playgroud)

Naw*_*waz 10

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

当成员模板专业化的名称出现之后.或 - >在postfix-expression中,或在qualified-id中的nested-name-specifier之后,postfix-expression或qualified-id显式依赖于template-parameter(14.6.2),成员模板名称必须是以关键字模板为前缀.否则,假定该名称命名非模板.

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

我必须在何处以及为何要使用"模板"和"typename"关键字?

  • 谢谢,这是我正在寻找的标准报价. (2认同)