简体   繁体   English

与类型同名的类型别名

[英]Type alias with same name as type

Is it valid C++? C++ 有效吗?

#include <iostream>


class Test {

    struct Inner {
    };

public:
    using Inner = struct Inner;  // Alias with same name as type
};

int main(int argc, const char * argv[]) {
    static_assert(std::is_pod<Test::Inner>::value, "");
    
    return 0;
}

Compile fine with clang but not with GCC / Visual C++ ("Inner is private..." error message)使用 clang 可以正常编译,但不能使用 GCC / Visual C++(“内部是私有的...”错误消息)

GCC and Visual C++ are correct. GCC 和 Visual C++ 是正确的。

Indeed you can use using to in effect change the access of a member, eg实际上,您可以使用using来有效地更改成员的访问权限,例如

using Inner_ = Inner;

with

static_assert(std::is_pod<Test::Inner_>::value, "");

in the function.在 function。

But in the case where the type alias has the same name as the member, C++ requires that the scope resolution operator looks up the member.但在类型别名与成员同名的情况下,C++ 需要 scope 解析运算符查找成员。 So in your case Test::Inner refers to the actual member rather than to the using and compilation should therefore fail as it's private .因此,在您的情况下, Test::Inner指的是实际成员而不是using ,因此编译应该失败,因为它是private


See https://en.cppreference.com/w/cpp/language/qualified_lookup , and in particular请参阅https://en.cppreference.com/w/cpp/language/qualified_lookup ,尤其是

Qualified lookup within the scope of a namespace N first considers all declarations that are located in N and all declarations that are located in the inline namespace members of N (and, transitively, in their inline namespace members).在命名空间 N 的 scope 内进行的限定查找首先考虑位于 N 中的所有声明以及位于 N 的内联命名空间成员(以及可传递地位于其内联命名空间成员中)的所有声明。 If there are no declarations in that set then it considers declarations in all namespaces named by using-directives found in N and in all transitive inline namespace members of N如果该集合中没有声明,则它会考虑在 N 中找到的使用指令命名的所有命名空间和 N 的所有传递内联命名空间成员中的声明

P1787R6: Declarations and where to find them , merged into C++23 draft, seems to favor Clang's behavior: P1787R6: Declarations and where to find them ,合并到 C++23 草案中,似乎有利于 Clang 的行为:

[basic.lookup] [基本.查找]

In certain contexts, only certain kinds of declarations are included.在某些情况下,仅包含某些类型的声明。 After any such restriction, any declarations of classes or enumerations are discarded if any other declarations are found .在任何此类限制之后,如果发现任何其他声明,则丢弃任何类或枚举的声明 [Note: A type (but not a typedef-name or template) is therefore hidden by any other entity in its scope. — end note] However, if a lookup is type-only , only declarations of types and templates whose specializations are types are considered; [注意:类型(但不是typedef 名称或模板)因此被其 scope 中的任何其他实体隐藏。 - 尾注]但是,如果查找是type-only ,则只有类型和模板的声明,其特化是类型被考虑; furthermore, if declarations of a typedef-name and of the type to which it refers are found, the declaration of the typedef-name is discarded instead of the type declaration.此外,如果找到typedef-name和它所引用的类型的声明,则丢弃typedef-name的声明而不是类型声明。

So the declaration of struct Inner is discarded, because the alias-declaration is found.所以struct Inner的声明被丢弃,因为找到了别名声明 (One can put Inner into type-only context — Test::struct Inner — and it will refer to the struct Inner declaration, per the second part of the paragraph). (可以将Inner放入仅限类型的上下文中Test::struct Inner根据本段的第二部分,它将引用struct Inner声明)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM