Topic: shared_from_this() from constructor


Author: =?ISO-8859-1?Q?Daniel_Kr=FCgler?= <daniel.kruegler@googlemail.com>
Date: Wed, 25 Aug 2010 23:57:18 CST
Raw View
On 26 Aug., 00:49, Florian Goujeon <florian.gouj...@42ndart.org>
wrote:
> The current GCC's implementation doesn't allow to call
> shared_from_this() from the class' constructor, just like the original
> Boost's implementation.
> Is this a standard-compliant behavior? The current draft doesn't talk
> about this.
> I hope it's not. This is really annoying...

A pre-condition of the call of

shared_ptr<T> shared_from_this();
shared_ptr<T const> shared_from_this() const;

are:

"*this shall be a subobject of an object t of type T. There
shall be at least one shared_ptr instance p that owns &t."

Can you satisfy this in your constructor?

If not: What do you want to realize?

HTH & Greetings from Bremen,

Daniel Kr   gler



--
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: Florian Goujeon <florian.goujeon@42ndart.org>
Date: Thu, 26 Aug 2010 13:11:10 CST
Raw View
Hi Daniel,


> A pre-condition of the call of
>
> shared_ptr<T> shared_from_this();
> shared_ptr<T const> shared_from_this() const;
>
> are:
>
> "*this shall be a subobject of an object t of type T. There
> shall be at least one shared_ptr instance p that owns &t."

Oh, sorry. I totally missed that paragraph. I should stop posting so
late...


> Can you satisfy this in your constructor?

This pre-condition cannot be satisfied in a constructor.
There must already be a shared_ptr instance that owns the object. But
that instance cannot exist during the execution of the object's
constructor, when the object in not created yet.


> If not: What do you want to realize?

Here is a typical case:
There is two classes: Container and Item.
Every Container object has a shared_ptr vector of Item objects.
Every Item object has a weak_ptr pointing to its parent Container
object.
The problem is that every Container object contains some Item objects
by default. These Item objects are created and added to the Container
object during its construction.
This is why I need to call shared_from_this() in the Container's
constructor.

A simple solution would be to write a make_container() factory
function which would create and add the default Item objects to the
Container. But this solution is not transparent for the users of
theses classes...

--
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: lucdanton <lucdanton@free.fr>
Date: Thu, 26 Aug 2010 13:10:22 CST
Raw View
On Aug 26, 12:49 am, Florian Goujeon <florian.gouj...@42ndart.org>
wrote:
> The current GCC's implementation doesn't allow to call
> shared_from_this() from the class' constructor, just like the original
> Boost's implementation.
> Is this a standard-compliant behavior? The current draft doesn't talk
> about this.
> I hope it's not. This is really annoying...

If what you're trying to do (but really, I can't tell if you don't) is
to register new objects somewhere, then the usual solution is to
separate concerns:
- have constructors private or protected: their concern is to setup
new instances with correct invariants (nothing unusual here)
- expose a (or several) public factory function that return shared_ptr
to new instances: their concern is to register new instances

Could be as simple as:

class Something;

/* could be part of the class, too */
void add_to_registry(std::shared_ptr<Something> const&);

/*  enabled_shared_from_this might or might not be necessary */
class Something: public std::enable_shared_from_this {
 /* whatever */

 template<typename ...T>
 static std::shared<Something> make(T&& ...t)
 {
   auto p = std::make_shared<Something>(std::forward<T>(t)...);
   add_to_registry(p);
   return p;
 }

};

Or maybe Something::make can return a reference to *p and the registry
takes care of lifetime management, if that's what you want.


--
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: Florian Goujeon <florian.goujeon@42ndart.org>
Date: Thu, 26 Aug 2010 15:45:39 CST
Raw View
Actually, the factory function is finally a pretty good solution
since - even without that default Item objects issue - if one tries to
add an Item object to a Container allocated on the stack (or on the
heap but without using a shared_ptr), an std::bad_weak_ptr will be
raised, as no shared_ptr instance will own that Container object.

Once the constructor of Container made private, a (friend) factory
function would force the user to allocate the Container objects on the
heap using a shared_ptr.

Sorry to the moderation for the double-post and thanks to you for your
help, Daniel.

--
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use
mailto:std-c++@netlab.cs.rpi.edu<std-c%2B%2B@netlab.cs.rpi.edu>
]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]