Usually I prefer returning unique_ptr
from Factories. Recently I came to the problem of returning a unique_ptr
for a class that inherits enable_shared_from_this
. Users of this class may accidentally cause a call to shared_from_this()
, though it is not owned by any shared_ptr
, which results with a std::bad_weak_ptr
exception (or undefined behavior until C++17, which is usually implemented as an exception).
A simple version of the code:
class Foo: public enable_shared_from_this<Foo> {
string name;
Foo(const string& _name) : name(_name) {}
public:
static unique_ptr<Foo> create(const string& name) {
return std::unique_ptr<Foo>(new Foo(name));
}
shared_ptr<Foo> get_shared() {return shared_from_this();}
void doIt()const {cout << "Foo::doIt() <" << name << '>' << endl;}
virtual ~Foo() {cout << "~Foo() <" << name << '>' << endl;}
};
int main() {
// ok behavior
auto pb1 = Foo::create("pb1");
pb1->doIt();
shared_ptr<Foo> pb2 = shared_ptr<Foo>(std::move(pb1));
shared_ptr<Foo> pb3 = pb2->get_shared();
pb3->doIt();
// bad behavior
auto pb4 = Foo::create("pb4");
pb4->doIt();
shared_ptr<Foo> pb5 = pb4->get_shared(); // exception
pb5->doIt();
}
A possible solution is to change the factory method to return shared_ptr
but this is not what I'm looking for, as in many cases there is actually no need for sharing and this will make things less efficient.
The question is how to achieve all of the following:
- allow the factory to return
unique_ptr
- allow
unique_ptr
of this class to become shared - allow
shared_ptr
of this class to get shared copies (viashared_from_this()
) - avoid failure when
unique_ptr
of this class tries to get shared from this (callingget_shared
in above example)
Items 1 to 3 are fulfilled with the code above, the problem is with item 4.
Aucun commentaire:
Enregistrer un commentaire