与类型同名的类型别名

Type alias with same name as type

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

使用 clang 可以正常编译,但不能使用 GCC/Visual C++(“Inner is private...”错误消息)

GCC 和 Visual C++ 是正确的。

您确实可以使用 using 来有效地更改成员的访问权限,例如

using Inner_ = Inner;

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

在函数中。

但在类型别名与成员同名的情况下,C++ 要求作用域解析运算符查找成员。因此,在您的情况下,Test::Inner 指的是实际成员而不是 using,因此编译应该失败,因为它是 private.


参见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). 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

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; 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.

因此 struct Inner 的声明被丢弃,因为找到了 alias-declaration。 (可以将 Inner 放入仅限类型的上下文中 - Test::struct Inner - 根据该段的第二部分,它将引用 struct Inner 声明。