C++:从类及其受保护的成员类型继承是否可以?

zwh*_*nst 12 c++ inheritance protected multiple-inheritance

以下代码符合C++标准吗?

struct B
{
protected:
    struct Type {};
};

struct D : B, B::Type
{};

int main()
{
    D d;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我在Compiler Explorer上试了一下.MSVC(VS 2017 RTW)接受它.gcc(7.3)和clang(6.0.0)拒绝它.

asc*_*ler 12

代码是标准兼容的,从C++ 11开始,但不在C++ 03中.

C++ 11到C++ 17在[class.access]部分,成员访问控制的介绍中说明了这一点:

子句[class.access]中的所有访问控制都会影响从特定实体的声明访问类成员名称的能力,包括声明的实体名称前面的声明部分,如果实体是类,则出现在类的成员规范之外的类成员的定义.

在那些相同的标准版本中,下面的示例非常类似于您的问题,但即使有点棘手:

[例:

  class A {
...
  protected:
      struct B { };
  };
...

  struct D: A::B, A { };
Run Code Online (Sandbox Code Playgroud)

... A::B作为基本说明符的使用是良好形式的,因为它D是派生自的A,因此必须推迟对基本说明符的检查,直到看到整个base-specifier-list.- 结束例子 ]

但我看到你做的结果相同:g ++和clang ++都拒绝这些程序,无论-std=我给出什么样的论据.这是一对编译器错误.

C++ 03有这个而不是我上面引用的第一段:

子句[class.access]中的所有访问控制都会影响从特定范围访问类成员名称的能力.对于出现在成员类定义之外的类成员定义中使用的名称的访问控制,就好像整个成员定义出现在成员类的范围内一样....

类定义的基本说明符不在该类的作用域中,因此C++ 03不允许使用受保护或私有名称作为派生类的基类名称,否则该类可以访问该名称.