两级嵌套 c++ 类适用于 GCC,但使用 Clang 失败

Posted

技术标签:

【中文标题】两级嵌套 c++ 类适用于 GCC,但使用 Clang 失败【英文标题】:Two level nested c++ class works with GCC but fails with Clang 【发布时间】:2013-05-26 12:01:01 【问题描述】:

在声明它的类之外定义内部类时遇到问题。

struct Base 
    struct A 
        struct B;
    ;
    struct A::B 
    ;
;

它可以编译并与 GCC 一起工作,但在 Clang 上失败并出现以下错误:

innerclass.cpp:6:12: error: non-friend class member 'B' cannot have a qualified name
    struct A::B 
           ~~~^

如果省略最外层的 Base 类,则代码适用于 Clang。

这样定义内部类是违法的吗?如果有,应该怎么做?

平台: OS X 10.8.3 XCode 4.6.2 Clang Apple LLVM 版本 4.2 (clang-425.0.24)(基于 LLVM 3.2svn) GCC gcc 版本 4.2.1(基于 Apple Inc. build 5658)(LLVM build 2336.11.00)

【问题讨论】:

【参考方案1】:

恐怕 GCC 会放任自流。 C++11 标准的第 9/1 段指定 class-head-name 是:

nested-name-specifier(opt) 类名

这意味着限定名称可以用作类的名称。此外,第 9/11 段的第一部分规定:

如果 class-head-name 包含 nested-name-specifier,则 class-specifier 应指那是 之前直接在 nested-name-specifier 引用的类或命名空间中声明,[...]

你确实在类A 中声明了类B。但是,同一段的第二部分添加了:

[...] 和 类说明符 应出现在包含先前声明的命名空间中。在这种情况下,定义的 class-head-namenested-name-specifier 不应以 decltype-specifier.

在您的情况下,class-specifier struct A::B 确实 出现在命名空间的范围内,而是出现在类的范围内(尝试更改 struct Base进入namespace Base,你会看到 Clang 接受它)。

因此,解决此问题的正确方法是在命名空间范围内定义类,而不是在 Base 内:

// ...

struct Base::A::B

;

【讨论】:

以上是关于两级嵌套 c++ 类适用于 GCC,但使用 Clang 失败的主要内容,如果未能解决你的问题,请参考以下文章

gcc 的 C++ 部分模板专业化问题

focus-within 适用于 Android 浏览器,但不适用于 iOS

宏调用中的 #ifdef 适用于 gcc,但不适用于 msvc

特定于 gcc 4.5 的 C++ 数组创建问题

嵌套函数在 gcc 中是一件坏事吗? [关闭]

GHC 找不到适用于 mingw gcc(但不是 mingw-w64)的外部库(libjack.lib)