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的错误是否正确.
笔记:
使用clang ++ 3.8和gcc 5.4进行测试,但Godbolt建议在最近的GCC版本中没有改变.
我查看了decltype和类成员名称之间的交互阴影外部名称,其中变量的名称可以指外部作用域中的变量或类成员.相比之下,我的问题是关于类型别名.由于Foo总是::Foo在类范围内引用,因此没有歧义.我看不出那里的答案如何适用于我的问题.
这可能是由于误解了实际上是什么类型的别名.
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.该规则的措辞是指引用声明,所以我认为海湾合作委员会是对的.