Получение unique_ptr для класса, который наследует enable_shared_from_this
Обычно я предпочитаю возвращатьсяunique_ptr
с заводов. Недавно я пришел к проблеме возвращенияunique_ptr
для класса, который наследуетenable_shared_from_this
, Пользователи этого класса могут случайно вызвать звонокshared_from_this()
, хотя он не принадлежит никомуshared_ptr
, что приводит кstd::bad_weak_ptr
исключение (или неопределенное поведение до C ++ 17, которое обычно реализуется как исключение).
Простая версия кода:
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();
}
Возможное решение состоит в том, чтобы изменить заводской метод для возвратаshared_ptr
но это не то, что я ищу, так как во многих случаях нет необходимости делиться, и это сделает вещи менее эффективными.
Вопрос в том, как добиться всего следующего:
разрешить фабрике вернутьсяunique_ptr
разрешатьunique_ptr
этого класса, чтобы стать общимразрешатьshared_ptr
этого класса, чтобы получить общие копии (черезshared_from_this()
)избежать неудачи, когдаunique_ptr
этого класса пытается получить общий доступ от этого (вызовget_shared
в приведенном выше примере)Пункты с 1 по 3 выполняются с кодом выше,проблема с пунктом 4.