首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >typedef改变了含义

typedef改变了含义
EN

Stack Overflow用户
提问于 2012-08-30 06:47:58
回答 2查看 5.8K关注 0票数 20

当我用g++编译以下代码片段时

代码语言:javascript
复制
template<class T>
class A
{};

template<class T>
class B
{
    public:
        typedef A<T> A;
};

编译器告诉我

代码语言:javascript
复制
error: declaration of ‘typedef class A<T> B<T>::A’
error: changes meaning of ‘A’ from ‘class A<T>’

另一方面,如果我将typedef更改为

代码语言:javascript
复制
typedef ::A<T> A;

使用g++可以很好地编译所有内容。无论哪种方式,Clang++ 3.1都不在乎。

为什么会发生这种情况?第二个行为标准是什么?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-08-30 07:07:22

g++是正确的,并且符合标准。来自3.3.7/1

在S级中使用的A名称N应在其上下文中引用相同的声明,并且在S的完整范围内重新评估时,不需要对违反本规则的情况进行诊断。

在类型定义函数之前,A引用了::A,但是通过使用类型定义函数,您现在使A引用禁止的类型定义函数。然而,由于no diagnostic is required,clang也是符合标准的。

jogojapan's comment解释了此规则的原因。对您的代码进行以下更改:

代码语言:javascript
复制
template<class T>
class A
{};

template<class T>
class B
{
    public:
        A a; // <-- What "A" is this referring to?
        typedef     A<T>            A;
};

由于类作用域的工作方式,A a;变得不明确。

票数 12
EN

Stack Overflow用户

发布于 2014-01-31 02:47:39

我将补充杰西的回答,关于GCC在编译过程中看似奇怪的行为:

代码语言:javascript
复制
typedef A<T> A;

vs

代码语言:javascript
复制
typedef ::A<T> A;

这也适用于使用以下形式的语句:

代码语言:javascript
复制
using A =   A<T>;
using A = ::A<T>;

在GCC内部似乎发生的事情是,在编译声明B::A的typedef/using语句期间,符号B::A成为using语句本身中的有效候选。也就是说,当说using A = A<T>;typedef A<T> A;时,GCC认为::AB::A都是A<T>的有效候选者。

这似乎是一种奇怪的行为,因为正如您的问题所暗示的那样,您不希望新的别名A成为typedef本身内的有效候选者,但正如Jesse的回答所说的那样,在类中声明的任何内容对类中的其他所有内容都是可见的-在这种情况下,显然甚至包括声明本身。这种类型的行为可以以这种方式实现,以允许递归类型定义。

正如您所发现的,解决方案是为GCC精确地指定您在typedef中引用的A,然后它就不再抱怨了。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/12187549

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档