Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Behavior of qualified name using private inheritance

When compiling the following example in msvc, I get

'Interface' not accessible because 'Base' uses 'private' to inherit from 'Interface'

in the line marked with Error. When the call to foo is qualified with a type alias of the same type, it works. I tested with msvc and ideone.

Why are the two calls not equal?

struct Interface {};

template<class T>
struct Base : private T
{
    void foo() {}
};

using BaseX =   Base<Interface>;

class Derived : Base<Interface>
{
    Derived() {
        Base<Interface>::foo();   // Error
        BaseX::foo();             // Works
    }
};

Ideone

like image 600
Beta Carotin Avatar asked Nov 04 '15 19:11

Beta Carotin


1 Answers

Injected-class-names.

The name Interface is injected into the scope of the class Interface as if it's a public member, and in turn inherited by Base<Interface> (as a private member, since you are using private inheritance).

When you write Base<Interface>::foo() in Derived, unqualified name lookup for Interface looks first at Derived and its base class, finds Interface in the base class, and then access control kicks in because that name is private.

The simplest fix is to just write Base::foo(), or even just foo() if it isn't virtual and you aren't planning to write a foo() in Derived.

If you have to include the template argument for some reason, then write Base<::Interface>.

like image 121
T.C. Avatar answered Nov 08 '22 22:11

T.C.