我可以使用相同的名称为周围范围中的类型声明成员类型别名吗?

amo*_*mon 10 c++ g++ type-alias clang++ c++14

我想要一个struct包含一个类型别名到另一个类型用于元编程目的:

struct Foo {};

struct WithNestedTypeAlias {
    using Foo = Foo;
};
Run Code Online (Sandbox Code Playgroud)

然后我可以像WithNestedTypeAlias::Foo模板等那样做.

据我所知,这种类型的别名是有效的,因为它不会改变Foo类型的含义.Clang愉快地编译了这个.

然而,海湾合作委员会抱怨:

test-shadow-alias.cpp:4:20: error: declaration of ‘using Foo = struct Foo’ [-fpermissive]
     using Foo = Foo;
                    ^
test-shadow-alias.cpp:1:8: error: changes meaning of ‘Foo’ from ‘struct Foo’ [-fpermissive]
 struct Foo {};
        ^
Run Code Online (Sandbox Code Playgroud)

现在我很困惑,因为我明确没有改变Foofrom 的含义struct Foo.

C++ 14的正确行为是什么?我知道我可以通过重命名来解决这个问题struct Foo,但是我想知道GCC的错误是否正确.

笔记:

Jon*_*ely 8

GCC强制执行的规则是[basic.scope.class]:

2)在S类中使用的名称N应在其上下文中引用相同的声明,并在完成的S范围内重新评估.违反此规则不需要诊断.

标准说违反此标准不需要诊断,因此GCC和Clang都可能符合要求,因为(如果GCC是正确的)代码无效,但编译器不需要诊断它.

此规则的目的是使类中使用的名称始终表示相同的内容,并且重新排序成员不会改变它们的解释方式,例如

struct N { };

struct S {
  int array[sizeof(N)];

  struct N { char buf[100]; };
};
Run Code Online (Sandbox Code Playgroud)

在此示例中,名称N更改含义,重新排序成员将更改大小S::array.当S::array被定义N指型::N,但在完成的范围S是指S::N代替.这违反了上面引用的规则.

在你的例子中,名称Foo以一种不太危险的方式改变,因为它仍然引用相同的类型,但严格地说,它确实从引用声明::Foo改为声明S::Foo.该规则的措辞是指引用声明,所以我认为海湾合作委员会是对的.

  • @amon:原始代码中的问题是右侧的`Foo`改变了意义,因为它不合格.在"using"声明之前,它将意味着全局Foo,后来它将意味着别名.如果它是合格的,那么这不再是一个问题. (3认同)
  • @amon还请注意[CWG 42](http://wg21.link/cwg42),它将回答你关于`Foo`,`:: Foo`和所有内容的问题. (2认同)