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

发布于 2024-11-11 17:07:24 字数 1172 浏览 3 评论 0原文

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

This snippet (taken from this question) compiles fine with g++ (as seen), so long the template before the return type is there. In contrast, VC10 does not compile that code with the following error:

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

If I remove the template, VC10 is happy but g++ screams this error:

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

Is it again because of VC's broken two-phase look-up or what is the cause? Which compiler is right here? I suspect g++ to be correct, as I have a vague memory of template being needed here, like with the rebind template inside of allocators.


Edit: We have a winner: g++/GCC (surprise surprise...).


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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

夜巴黎 2024-11-18 17:07:24

海湾合作委员会是对的。 AttributeType 是一个依赖的模板名称,后面是尖括号 <,因此这里需要关键字 template 来消除歧义1,让编译器清楚后面的是模板名称。 §14.2/4 中提到了该规则:

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

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

我必须在哪里以及为什么必须放置“template”和“typename”关键字?

GCC is right. AttributeType is a dependent template-name which is followed by angle bracket <, so the keyword template is required here to remove the ambiguity1, making it clear to the compiler that what is followed is a template-name. The rule is mentioned in §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.

1 @Johannes has written a very good explanation here:

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文