2011-06-03 27 views
15

This snippet(取自this question)用g ++编译得很好(如图所示),只要返回类型之前的template就在那里。相比之下,VC10不会编译代码,出现以下错误:哪个编译器是正确的?模板返回类型之前需要'模板'吗?

error C2244: 'A::getAttr' : unable to match function definition to an existing declaration

如果我删除了template,VC10是幸福的,但G ++惨叫此错误:再次因为VC的破碎

error: non-template 'AttributeType' used as template
note: use 'A::template AttributeType' to indicate that it is a template

是它两阶段查找或原因是什么?哪个编译器就在这里?我怀疑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; 
} 
+3

邮政问题的代码。堆栈溢出支持并强烈鼓励这一点。 – 2011-06-03 20:29:07

+1

一般来说,标准合规的非正式“参考编译器”是Comeau,您可以尝试提交您的代码片段(http://www.comeaucomputing.com/tryitout/)来查看其判断。 - 编辑:现在尝试,该片段编译它很好,因为它是在Ideone。 – 2011-06-03 20:29:30

+0

@Merlyn:想要保持这个问题简短,尽管如此。 – Xeo 2011-06-03 20:31:08

回答

10

GCC是正确的。 AttributeType是一个依赖的模板名称,后面跟着尖括号<,因此在这里需要使用关键字template来消除模糊性,这使得编译器清楚接下来是模板名称。该规则在§14.2/ 4提到:

When the name of a member template specialization appears after . or -> in a postfix-expression, or after nested-name-specifier in a qualified-id, and the postfix-expression or qualified-id explicitly depends on a template-parameter (14.6.2), the member template name must be prefixed by the keyword template. Otherwise the name is assumed to name a non-template.

@Johannes已经写在这里很好的解释:

Where and why do I have to put the "template" and "typename" keywords?

+2

谢谢,那是我正在寻找的标准报价。 – Xeo 2011-06-03 21:02:35