Follow-up question to this one.
Basically, in the following code, why does the compiler think that the B
inside A<B>
in C
s constructor refer to the (inaccessible) constructor of the B
base class?
struct B{};
template <typename T>
struct A : private T{};
struct C : public A<B>{
C(A<B>); // ERROR HERE
};
Live example on Ideone. Output:
prog.cpp:1:9: error: 'struct B B::B' is inaccessible
prog.cpp:7:7: error: within this context
Note that the same error pops up if you change the constructor argument to A<B*>
, A<B&>
or even A<const B>
. Also note that three of MSVC10, GCC 4.7 and Clang 3.1 ToT will error out, so it must be something in the C++ spec. What is it?
The standard allows injected class names to be less accessible than the original names. This is even mentioned in a note in §11.1/5, together with an example:
[ Note: In a derived class, the lookup of a base class name will find the injected-class-name instead of the name of the base class in the scope in which it was declared. The injected-class-name might be less accessible than the name of the base class in the scope in which it was declared. —end note ]
[ Example:
class A { }; class B : private A { }; class C : public B { A *p; // error: injected-class-name A is inaccessible ::A *q; // OK };
—end example ]
Accessing A
unqualified uses the injected name, which is not accessible because it comes from private inheritance. Accessing A
qualified uses the declared name, which is accessible in the global scope.
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