Search code examples
c++c++11shared-ptr

Why enable_shared_from_this must be publicly inherited?


I just had an hard time understanding why this code was throwing. All the other solutions on SO said you need to have a shared_ptr instance in order to use shared_from_this(), and I had it! But nonetheless, the code was still crashing like all the other questions were describing.

Here is a simplified version of the code

main.cpp

uint16_t port = 9876;
auto inout = cms::MultiTcpInOut::create(port);
inout->start_accept();

MultiTcpInOut.h

#ifndef MULTITCPINOUT_H
#define MULTITCPINOUT_H

#include <memory>
#include <utility>

namespace cms {

    using namespace std;

    class MultiTcpInOut : private enable_shared_from_this<MultiTcpInOut>
    {
        public:
            static shared_ptr<MultiTcpInOut> create(uint16_t port)
            {
                return shared_ptr<MultiTcpInOut>(new MultiTcpInOut(port));
            }

            virtual ~MultiTcpInOut();

            // start_accept() can not be called from the constructor because it uses shared_from_this(), and
            // make_shared<>() haven't finished yet when it is called. Let the instantiating code call it
            void start_accept();

        protected:
            MultiTcpInOut(uint16_t port);
    };
}
#endif // MULTITCPINOUT_H

MultiTcpInOut.cpp

void MultiTcpInOut::start_accept()
{
    LOG(INFO) << "Starting accept";
    auto socket = make_shared<tcp::socket>(io_service);
    auto shrd_this = shared_from_this();
    acceptor->async_accept(*socket.get(), bind(&MultiTcpInOut::handle_accept, shrd_this, socket, std::placeholders::_1));
}

Changing the private enable_shared_from_this<MultiTcpInOut> to public enable_shared_from_this<MultiTcpInOut> fixed the problem.

Nowhere it says it must be inherited publicly (at least reading the reference), and I don't understand why it has not, since I was calling it from a class method!

So, why does it have to be public? Is it so clear that it's not mentioned in the spec?

To help someone which might have my same problem

ENABLE_SHARED_FROM_THIS MUST BE INHERITED AS PUBLIC!!!


Solution

  • This is from cppreference: 'A common (until C++17)standard (since C++17) implementation for enable_shared_from_this is to hold a weak reference (such as std::weak_ptr) to this. The constructors of std::shared_ptr detect the presence of an enable_shared_from_this base and assign the newly created std::shared_ptr to the internally stored weak reference.' That is, std::shared_ptr<> needs write access to this field, not just your class.