I understand why shared_from_this doesn't work in the constructor. I've found a number of posts on here clearly explaining why. I've also seen a workaround for it. My problem is related to this but I'm looking for an elegant workaround.
I quite like this kind of design
class Foo : public enable_shared_from_this<Foo> {
public:
typedef shared_ptr<Foo> Ptr;
Ptr setA(int) {/* .... */ return this->shared_from_this(); }
Ptr setB(int) {/* .... */ return this->shared_from_this(); }
Ptr setC(int) {/* .... */ return this->shared_from_this(); }
};
so I can daisy chain like this, which I find very readable
Foo::Ptr foo = make_shared<Foo>();
foo->setA(3)->setB(4)->setC(5);
However, my setX methods do more than just assign the value to a property, they might do slightly more complex things (like set other properties etc). So I'd like to use them in my constructor. i.e.
Foo::Foo(int a, int b, int c) {
setA(a);
setB(b);
setC(c);
}
Of course this crashes. However in my case I don't actually need a shared this pointer in my constructor. It's just a side-effect of my wanting to daisy chain later.
A dirty fix could be I just make a bunch of private setX_ methods which do the actual assignment and other tasks, but don't return anything. The constructor calls those. Then I have public setX methods simply call the private ones and then return the this->shared_from_this(). That's safe, but a bit of a PITA. Is it possible to check if a shared pointer to this already exists without crashing? i.e.
class Foo : public enable_shared_from_this<Foo> {
public:
typedef shared_ptr<Foo> Ptr;
Ptr setA(int) { /*.....*/ return getThis(); }
protected:
Ptr getThis() {
return safe_to_get_this ? this->shared_from_this : Ptr();
}
};
UPDATE
I should have made this clear in my original post, apologies for not doing so. The reason I'm using smart pointers is not so I can do daisy chaining. I usually use references for that if the situation permits.
But in this case Foo (and other classes) belong to a graph like structure, they have dependencies on each other, multiple parent-child-sibling relationships etc. So I use a mix between shared and weak pointers. But I need the methods to return shared_ptrs, so I can cast to weak or check against null if need be (They are created with factory methods, and there are find/get methods too which need checking against null). Basically it's a physics system with different types of particles and constraints between particles. I originally wrote this with my own smart pointer implementation many years ago, and now I'm upgrading it to c++11. I could make the setX methods return references, and have a single getThis() method return the shared pointer (which is what I was doing before), but then I'm worried it becomes a bit inconsistent with some methods returning smart pointers others returning references.
Foo::Ptr foo = World::create();
foo->setA().setB().setC();
foo = World::find(...);
if(foo) foo->setA().setB();
I just prefer the consistency of always returning pointers, as opposed to sometimes pointers and sometimes references. Unless there is a strict guideline for this that can be summarized succinctly.
UPDATE2
This is the (not very elegant) workaround I'm using currently. I was just wondering if there was a way of doing this without manually keeping track of _isInited;
class Foo : public enable_shared_from_this<Foo> {
public:
typedef shared_ptr<Foo> Ptr;
Foo() {
_isInited = false;
setA();
setB();
setC();
_isInited = true;
}
Ptr setA(int) {/* .... */ return getThis(); }
Ptr setB(int) {/* .... */ return getThis(); }
Ptr setC(int) {/* .... */ return getThis(); }
protected:
bool _isInited;
Ptr() {
return _isInited ? this->shared_from_this() : Ptr();
}
};