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.
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 becauseD
is derived fromA
, 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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With