Obtener un unique_ptr para una clase que hereda enable_shared_from_this

Normalmente prefiero regresarunique_ptr de las fábricas. Recientemente llegué al problema de devolver ununique_ptr para una clase que heredaenable_shared_from_this. Los usuarios de esta clase pueden provocar accidentalmente una llamada ashared_from_this(), aunque no es propiedad de ningúnshared_ptr, que resulta con unstd::bad_weak_ptr excepción (o comportamiento indefinido hasta C ++ 17, que generalmente se implementa como una excepción).

Una versión simple del código:

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();    
}

Una posible solución es cambiar el método de fábrica para devolvershared_ptr pero esto no es lo que estoy buscando, ya que en muchos casos no hay necesidad de compartir y esto hará que las cosas sean menos eficientes.

La pregunta es cómo lograr todo lo siguiente:

permitir que la fábrica regreseunique_ptrpermitirunique_ptr de esta clase para ser compartidapermitirshared_ptr de esta clase para obtener copias compartidas (a través deshared_from_this())evitar el fracaso cuandounique_ptr de esta clase intenta ser compartida a partir de esto (llamandoget_shared en el ejemplo anterior)

Los artículos 1 a 3 se cumplen con el código anterior,el problema es con el ítem 4.

Respuestas a la pregunta(6)

Su respuesta a la pregunta