1

I have this code:

#include <memory>

class SomeInterface {
public:
    virtual void VirtualMethod() {}

    virtual void PureVirtualMethod() = 0;
};

class SomeInterfaceDependent {
public:
    explicit SomeInterfaceDependent(SomeInterface* a) : a_(a) {}

private:
    SomeInterface* const a_;
};

class Implementation : protected SomeInterface {
public:
    void Init() {
        // Ok
        auto raw = new SomeInterfaceDependent(this);

        // Cannot cast 'Implementation' to its protected base class 'SomeInterface'.
        auto shared = std::make_shared<SomeInterfaceDependent>(this);

        // Ok
        SomeInterface* casted_some_interface = this;
        auto shared2 = std::make_shared<SomeInterfaceDependent>(casted_some_interface);
    }

protected:
    void PureVirtualMethod() override {}
};


int main() {
    Implementation i;
    i.Init();

    return 0;
}

C++ standard 17, compiler GCC.

I get error error: ‘SomeInterface’ is an inaccessible base of ‘Implementation’ when (and):

  • SomeInterface inherited with protected access modifier.
  • SomeInterfaceDependent created using std::make_shared.
  • SomeInterface casted implicitly.

Why? Is it the std::make_shared bug?

Nicol Bolas
  • 449,505
  • 63
  • 781
  • 982
mooko
  • 109
  • 1
  • 4
  • `make_shared` ist just some function. It's not a friend of `Implementation`, hence it's not allowed to convert `Implementation* -> SomeInterface*` which it needs in order to call the constructor `SomeInterfaceDependent(SomeInterface*)` for the failing `make_shared`. It needs to do so internally because it takes its arguments with the types they currently have, and not with the types they need to be converted to in the end. – dyp Feb 08 '21 at 16:26
  • Re: "casted implicitly" -- that should be "converted implicitly". A cast is something you write in your source code to tell the compiler to do a conversion. A cast is always explicit. – Pete Becker Feb 08 '21 at 18:34

2 Answers2

2

Is it the std::make_shared bug?

No.

Why?

std::make_shared is not a friend of Implementation, and therefore it doesn't have access to its non-public bases, and therefore it cannot implicitly convert the pointer.

eerorika
  • 232,697
  • 12
  • 197
  • 326
0

protected inheritance is NOT public to external classes.

Because of this, the compiler does not have visibility to see that Implementation inherits from SomeInterface, and will say its cannot do the cast.

N. Prone
  • 180
  • 7
  • The compiler certainly "sees" that `Implementation` inherits from `SomeInterface`; it's right there in the source code! The problem is that the compiler is not allowed to do that conversion on its own. – Pete Becker Feb 08 '21 at 18:37
  • I guess I would re-word it to say "Since the inheritance is protected, only the inheriting class has knowledge that it is a derivative." – N. Prone Feb 08 '21 at 19:59