哪个编译器是正确的?模板返回类型之前需要'模板'吗?
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;
}
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?
谢谢,那是我正在寻找的标准报价。 – Xeo 2011-06-03 21:02:35
邮政问题的代码。堆栈溢出支持并强烈鼓励这一点。 – 2011-06-03 20:29:07
一般来说,标准合规的非正式“参考编译器”是Comeau,您可以尝试提交您的代码片段(http://www.comeaucomputing.com/tryitout/)来查看其判断。 - 编辑:现在尝试,该片段编译它很好,因为它是在Ideone。 – 2011-06-03 20:29:30
@Merlyn:想要保持这个问题简短,尽管如此。 – Xeo 2011-06-03 20:31:08