我可以使用相同的名称为周围范围中的类型声明成员类型别名吗? [英] May I declare a member type alias to a type in a surrounding scope, using the same name?

查看:225
本文介绍了我可以使用相同的名称为周围范围中的类型声明成员类型别名吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

出于元编程的目的,我希望结构包含另一个类型的类型别名:

I want a struct to contain a type alias to another type for metaprogramming purposes:

struct Foo {};

struct WithNestedTypeAlias {
    using Foo = Foo;
};

然后我可以在模板等中做类似WithNestedTypeAlias::Foo之类的事情.

Then I can do stuff like WithNestedTypeAlias::Foo in a template etc.

据我了解,此类型别名是有效的,因为它不会更改Foo类型的含义. Clang可以愉快地编译它.

As I understand, this type alias is valid because it does not change the meaning of the Foo type. Clang compiles this happily.

但是,GCC抱怨:

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

现在我很困惑,因为我没有明确地将Foo的含义从struct Foo更改.

Now I'm confused because I'm explicitly not changing the meaning of Foo from struct Foo.

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

What is the correct behaviour for C++14? I know I can work around this by renaming the struct Foo, but I'd like to understand whether GCC's error is correct here.

注意:

我查看了 decltype和类成员名称之间的交互作用,以掩盖外部名称,其中 variable 可以引用外部作用域中的变量或类成员.相比之下,我的问题是关于类型别名的.由于Foo在类范围内始终引用::Foo,因此没有歧义.我看不出那里的答案如何适用于我的问题.

I looked at Interaction between decltype and class member name shadowing an external name, where the name of a variable may refer to either a variable in the outer scope or to a class member. In contrast, my question here is about a type alias. There is no ambiguity since Foo always refers to ::Foo within the class scope. I don't see how the answer there applies to my problem.

这可能是由于对别名实际上是什么类型的误解.

This is probably due to a misunderstanding of what type aliases actually are.

推荐答案

GCC执行的规则在[basic.scope.class]中:

The rule GCC is enforcing is in [basic.scope.class]:

2)在S类中使用的名称N在上下文中以及在S的完整范围中进行重新评估时应引用相同的声明.对于此规则的违反,无需进行诊断.

2) A name N used in a class S shall refer to the same declaration in its context and when re-evaluated in the completed scope of S. No diagnostic is required for a violation of this rule.

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

The standard says violating this doesn't require a diagnostic, so it's possible that both GCC and Clang are conforming, because (if GCC is right) the code is not valid, but the compiler is not required to diagnose it.

此规则的目的是使类中使用的名称始终具有相同的含义,并且对成员进行重新排序不会改变它们的解释方式,例如

The purpose of this rule is so that names used in a class always mean the same thing, and re-ordering members doesn't alter how they are interpreted e.g.

struct N { };

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

  struct N { char buf[100]; };
};

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

In this example the name N changes meaning, and reordering the members would change the size of S::array. When S::array is defined N refers to the type ::N but in the completed scope of S it refers to S::N instead. This violates the rule quoted above.

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

In your example the name Foo changes in a far less dangerous way, because it still refers to the same type, however strictly speaking it does change from referring to the declaration of ::Foo to the declaration of S::Foo. The rule is phrased in terms of referring to declarations, so I think GCC is right.

这篇关于我可以使用相同的名称为周围范围中的类型声明成员类型别名吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆