Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++: Is It OK to Inherit from a Class and Its Protected Member Type?

Is the following code C++ standard compliant?

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

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

int main()
{
    D d;
    return 0;
}

I tried it on Compiler Explorer. MSVC(VS 2017 RTW) accepts it. gcc(7.3) and clang(6.0.0) reject it.

like image 722
zwhconst Avatar asked Mar 25 '18 04:03

zwhconst


1 Answers

The code is standard compliant and was since C++11, but was not in C++03.

C++11 through C++17 say this in the introduction to section [class.access] , Member Access Control:

All access controls in clause [class.access] affect the ability to access a class member name from the declaration of a particular entity, including parts of the declaration preceding the name of the entity being declared and, if the entity is a class, the definitions of members of the class appearing outside the class's member-specification.

In those same Standard versions, an example follows which is very much like your question, but even a bit trickier:

[Example:

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

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

... The use of A::B as a base-specifier is well-formed because D is derived from A, so checking of base-specifiers must be deferred until the entire base-specifier-list has been seen. -end example]

But I see the same results you did: g++ and clang++ both reject these programs, no matter what -std= argument I give. This is a pair of compiler bugs.

C++03 has this instead of the first paragraph I quoted above:

All access controls in clause [class.access] affect the ability to access a class member name from a particular scope. The access control for names used in the definition of a class member that appears outside of the member's class definition is done as if the entire member definition appeared in the scope of the member's class....

The base-specifier of a class definition is not in that class's scope, so C++03 does not allow using a protected or private name as the name of a base class for a derived class that otherwise has access to that name.

like image 180
aschepler Avatar answered Nov 09 '22 19:11

aschepler