Consider the following code:
struct Foo : std::enable_shared_from_this<Foo>
{
};
struct Bar
{
Foo foo;
};
int main()
{
std::shared_ptr<Bar> bar_p(new Bar);
//make shared_ptr to member with aliasing constructor
std::shared_ptr<Foo> foo_p(bar_p, &bar_p->foo);
assert(bar_p->foo.shared_from_this()); //fail! throws bad_weak_ptr
}
Unfortunately, it doesn't work as expected (at least in GCC 4.8.2). I looked into code and it seems that aliasing constructor simply doesn't call __enable_shared_from_this_helper()
which is necessary for proper work of shared_from_this()
.
Does anybody have any idea why it was designed in such a way? Is there something wrong with returning shared_ptr to member from shared_from_this?
[util.smartptr.shared.const]
template<class Y> shared_ptr(const shared_ptr<Y>& r, T* p) noexcept;
Effects: Constructs a
shared_ptr
instance that storesp
and shares ownership withr
.
foo_p
takes no ownership of bar_p->foo
when you call the aliasing constructor, which in this case is a very good thing because otherwise it would try to delete
it on destruction.
[util.smartptr.enab]
shared_ptr<T> shared_from_this();
shared_ptr<T const> shared_from_this() const;
Requires: [...]There shall be at least one
shared_ptr
instance p that owns&t
.
As bar_p->foo
isn't owned by at least one shared_ptr
you end up with undefined behavior, gcc throws bad_weak_ptr
but it isn't obliged to do anything helpful.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With