stas
stas

Reputation: 329

Detecting if a object is owned by a smart pointer

I have a class which derives from enable_shared_from_this and a method which returns a shared pointer by calling shared_from_this(). I would like to in that method detect if the object is owned by a shared_ptr and if not throw. I tried something like this:

shared_ptr<T> getPointer() {
    shared_ptr<T> ptr(shared_from_this()));
    if(!ptr)
        throw "Not owned by smart pointer"
    return ptr;
}

This doesn't work though because a bad weak pointer exception is thrown during the construction of ptr. Is there another way.

Upvotes: 1

Views: 1355

Answers (3)

Griffort
Griffort

Reputation: 1306

I also had the same issue. Fortunately C++17 added "weak_from_this", which is helpful since it provides a copy of the weak_ptr from within std::enable_shared_from_this regardless of whether the instance is being managed from a shared pointer.

Simply checking if this->weak_from_this().expired() (which is the same as checking use_count() == 0 according to the standard) appears to do the trick.

To the person reading this in 2034, hope it helps!

Upvotes: 0

James McNellis
James McNellis

Reputation: 355039

One of the preconditions of calling shared_from_this() for an object t is "there must exist at least one shared_ptr instance p that owns t" (see the Boost documentation). The C++11 specification of enable_shared_from_this has the same requirement.

As there are no other (documented) members of enable_shared_from_this, it appears there is no way to test whether an object derived from enable_shared_from_this is actually owned by a shared_ptr.

That said, for the sake of clarity, it would probably be best to derive from enable_shared_from_this only if objects of that type will always be owned by a shared_ptr. That way there is no confusion.

Upvotes: 3

Dietmar K&#252;hl
Dietmar K&#252;hl

Reputation: 153810

Looking at the interface in the standard, I can't see anything which would do a decent test. Of course, you can always hack around the problem:

std::shared_ptr<T> getPointer() {
    try {
        return this->shared_from_this());
    }
    catch (std::bad_weak_ptr const&) {
        throw std::runtime_error("not owned by smart pointer");
    }
}

Of course, you could as well just not catch the std::bad_weak_ptr exception and have the original exception escape the function.

BTW, when throwing an exceptin it is trongly advised to throw an exception derived from std::exception. If you ever got an exception you know nothing you'll curse the guy who created it because it isn't always easy to get hold of that exception to find out what it is about (although debuggers can help, if necessary by setting a break point into the internal function throwing the exception). It is much easier to just write the result of what().

Upvotes: 3

Related Questions