在父 class 中定义子 class 的子结构

Defining sub-structure of sub-class inside parent class

考虑以下代码片段:

class MyClass
{
private:
    struct PrivateClass
    {
        struct SubStruct;
    };

public:
    struct PrivateClass::SubStruct {};

private:
    PrivateClass::SubStruct member;
};

MSVC 和 gcc 编译这段代码没有任何错误。但是,clang 会产生以下错误:

<source>:10:26: error: non-friend class member 'SubStruct' cannot have a qualified name
    struct PrivateClass::SubStruct {};

那么,谁是对的?这是 clang 错误吗?

根据 C++ 17 标准中的 [class]/11

If a class-head-name contains a nested-name-specifier, the class-specifier shall refer to a class that was previously declared directly in the class or namespace to which the nested-name-specifier refers, or in an element of the inline namespace set (10.3.1) of that namespace (i.e., not merely inherited or introduced by a using-declaration), and the class-specifier shall appear in a namespace enclosing the previous declaration. In such cases, the nested-name-specifier of the class-head-name of the definition shall not begin with a decltype-specifier.

看来 clang 编译器是对的。

标准(最新草案)说:

[class.nest]

If class X is defined in a namespace scope, a nested class Y may be declared in class X and later defined in the definition of class X or be later defined in a namespace scope enclosing the definition of class X.

在此示例中,在 class PrivateClass 中声明的 class SubStruct 既不在稍后的 PrivateClass 中定义,也不在稍后的 a 中定义命名空间范围(而是稍后在外部 MyClass 的 class 范围内)。 PrivateClass 本身也不在命名空间范围内定义。

除非有另一条规则允许这样做,否则至少不会明确允许示例中的子嵌套 class 的定义。 Clang 似乎是正确的。