Reputation: 329
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
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
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
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