On Tue, Feb 5, 2013 at 2:10 AM, Dominique Devienne <ddevienne@gmail.com> wrote:
On Mon, Feb 4, 2013 at 6:23 PM, Nathan Crookston
<nathan.crookston@gmail.com> wrote:
>> Since Foo embeds a weak_ptr, why can't it new the pi_ on the spot?
>> (I'm using Boost 1.44).
>
> Hmm, it might be interesting to have shared_from_this create a shared_ptr if
> none exists, but I don't know what that might complicate -- perhaps it would
> cause issues at destruction?

I don't see the difference between the shared_ptr being created from
the "inside" or the "outside", as far as that pi_ is concerned.

>> PS: On a related note, why doesn't boost::shared_ptr<Foo>(p_foo)
>> (where p_foo is a raw Foo*) implicitly apply the aliasing Ctor, to
>> share the same px, to avoid the classic bug of having several
>> different pn on the same px, since p_foo derives from
>> enable_shared_from_this()? Initially i thought that's what
>> sp_enable_shared_from_this() and pe->_internal_accept_owner() were
>> meant to do, but obviously that's not the case.
>
> I suspect something like this could be made to work if the previous also
> worked -- but the class is documented to *not* allow the previous to work.
> I'd have to think about why (or maybe Peter will enlighten us).

Indeed, I (naively) think it can work, and I'm interested in finding
out why this was not implemented, especially whether it was conscious
decision (rational?) or simply overlooked.

Consider this simple example:

int MyThing::Foo()
{
    shared_from_this();
    return this->x;
}
 
If enable_shared_from_this created a shared_ptr for you, then the last reference would have been destroyed and this would be deleted, leading to undefined behavior. A real-world example might be passing shared_from_this() as part of a callback to some function (or any other of the uses of enable_shared_from_this). Your proposal would make legitimate-looking code lead to undefined behavior depending on how the instance was constructed (if it was stored in a shared_ptr). This would be doubly-confusing if you used shared_from_this() in the constructor. And then you'd have to figure out a way to let a unique_ptr<MyThing> know that it no longer uniquely owns the instance. Or somehow deal with a stack-allocated MyThing.

In the current implementation, the call to shared_from_this() will always throw a boost::bad_weak_ptr. Sure, it is inconvenient, but it doesn't lead to undefined behavior. I see that as a major advantage.


Thanks for any insight on this. Could very well be I'm missing
something obvious (my C++ expertise doesn't rise to Boost levels), but
so far I fail to see the drawbacks.

I would suggest looking at intrusive_ptr (http://www.boost.org/doc/libs/1_52_0/libs/smart_ptr/intrusive_ptr.html) or the not-really-documented enable_shared_from_this2 (http://www.boost.org/doc/libs/1_52_0/boost/smart_ptr/enable_shared_from_this2.hpp). Neither solves every problem under the sun, but they might have helpful properties you're looking for.

There's already code that tightly couples
shared_ptr/weak_ptr/enable_shared_from_this,

I would disagree with the statement that shared_ptr and weak_ptr are coupled with enable_shared_from_this -- they can exist perfectly fine without them (but enable_shared_from_this can't exist without both). The only coupling shared_ptr has with weak_ptr is inside the implementation (arguably bad, but whatever).

--
Travis Gockel
λ Combinator