pur*_*ess 5 c++ declaration definition inner-classes language-lawyer
考虑以下代码片段:
class MyClass
{
private:
struct PrivateClass
{
struct SubStruct;
};
public:
struct PrivateClass::SubStruct {};
private:
PrivateClass::SubStruct member;
};
Run Code Online (Sandbox Code Playgroud)
MSVC和gcc编译此代码没有任何错误。但是,clang会产生以下错误:
<source>:10:26: error: non-friend class member 'SubStruct' cannot have a qualified name
struct PrivateClass::SubStruct {};
Run Code Online (Sandbox Code Playgroud)
那么,谁是对的?这是叮当声的错误吗?
根据[class]/11C ++ 17标准:
如果一个类名包含一个嵌套名称说明符,则该类说明符应引用先前在该嵌套名称说明符所引用的类或名称空间中或在其元素中直接声明的类。该名称空间的内联名称空间集(10.3.1)(即,不仅由using-声明继承或引入),并且class-specifier应出现在包含先前声明的名称空间中。在这种情况下,定义的类头名称的嵌套名称说明符不应以decltype-specifier开头。
因此,似乎clang编译器是正确的。
标准(最新草案)说:
[类.巢]
如果类 X 是在命名空间范围中定义的,则可以在类 X 中声明嵌套类 Y,然后在类 X 的定义中进行定义,或者稍后在包含类 X 的定义的命名空间范围中进行定义。
SubStruct在此示例中,在类中声明的类PrivateClass既不是PrivateClass在命名空间作用域中的后面定义的,也不是在命名空间作用域的后面定义的(而是在外部的类作用域的后面定义的MyClass)。它本身也没有PrivateClass在命名空间范围中定义。
除非有其他规则允许这样做,否则至少不会明确允许示例中的子嵌套类的定义。铿锵似乎是正确的。