c++shared-ptr

C++ shared_ptr from *this, parent and derived classes


I need to get a shared_ptr from this, which is easy for a parent class. But when you start deriving from this class - the issue is more difficult.

You get this error:

 member 'shared_from_this' found in multiple base classes of different types
        return this->shared_from_this();                     ^
note: member found by ambiguous name lookup

How should I approach this?

#include <memory>

struct AAA : std::enable_shared_from_this<AAA>
{
    auto getA() -> std::shared_ptr<AAA> { return this->shared_from_this(); }
};

struct BBB : AAA, std::enable_shared_from_this<BBB>
{
    auto getB() -> std::shared_ptr<BBB> { return this->shared_from_this(); }
};

EDIT:

The reason for this convoluted code, is that I want my API to be designed in such way that you have setters - that return "self" and then you have chainability. Originally the setters would return a reference to self, but then code looks ugly (see the conversion from a pointer, to a reference):

// Before
auto a = std::make_shared<AAA>();
a->set_attrZ(1)
   .set_attrK(2);

auto b = std::make_shared<BBB>();
b->set_attr1A(1)
   .set_attrB(2)
   .set_callback(()[]{ /* */ });

// After
auto a = std::make_shared<AAA>()
   -> set_attrZ(1)
   -> set_attrK(2);

auto b = std::make_shared<BBB>()
   -> set_attrA(1)
   -> set_attrB(2)
   -> set_callback( ()[]{ /* */ });

// note that in some cases you might not need to maintain the reference - this may download a json from server and handle the data in the callback.
std::make_shared<BBB>()
   -> set_attrA(1)
   -> set_attrB(2)
   -> set_callback( ()[]{ /* */ })
   -> do_some_work();

Solution

  • I think you want:

    struct BBB : AAA
    {
        auto getB() -> std::shared_ptr<BBB> { 
            auto spA = getA();
            auto spB = std::static_pointer_cast<BBB>(spA);
            return spB;
        }
    };
    

    Or this:

    struct BBB : AAA, std::enable_shared_from_this<BBB>
    {
        auto getB() -> std::shared_ptr<BBB> { 
            std::enable_shared_from_this<BBB>* sftB = this;
            return sftB->shared_from_this();
        }
    };
    

    I like the former better than the latter. The former doesn't create such a muddled inheritance tree.