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

Check whether an object derived from enable_shared_from_this is managed by shared_ptr?


Suppose I have a class derived from std::enable_shared_from_this

struct foo
  : std::enable_shared_from_this<foo>
{
    std::shared_ptr<foo> get_shared()
    {
        return shared_from_this();
    }

    bool is_shared() const
    {
        /* implementation ??? */
    }
};

foo  A;
auto S= A.get_shared();   // UB (pre c++17) or exception (c++17)

Prior to c++17, there appears to be no way to detect whether an object foo is actually managed by a shared_ptr. Correct?

But even for c++17, I'm not sure how to best implement such a detection. One obvious approach is

bool foo::is_shared() const
{
    try {
        shared_from_this();
    } catch(...) { 
        return false;
    }
    return true;
}

But can the try-catch be avoided? Can I use weak_from_this()? How?


Solution

  • You can implement is_shared leveraging weak_from_this() in C++17 like:

    bool is_shared() const
    {
        return !weak_from_this().expired();
    }
    

    This is exception free and will only return true is the object is actually managed by a shared_ptr.

    Pre C++17 there isn't a way to check since it is undefined behavior to call shared_from_this() when the object is not owned by a shared_ptr. It wasn't until weak_from_this() was introduced in C++17 that we could access the private weak_ptr member of std::enable_shared_from_this (via a copy) that we can inspect the state in a defined manner.