Obtendo um unique_ptr para uma classe que herda enable_shared_from_this

Normalmente eu prefiro voltarunique_ptr de Fábricas. Recentemente, cheguei ao problema de retornar umunique_ptr para uma classe que herdaenable_shared_from_this. Os usuários desta classe podem acidentalmente causar uma chamada parashared_from_this(), embora não seja de propriedade de nenhumshared_ptr, o que resulta com umstd::bad_weak_ptr exceção (ou comportamento indefinido até C ++ 17, que geralmente é implementado como uma exceção).

Uma versão simples do 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();    
}

Uma solução possível é alterar o método de fábrica para retornarshared_ptr mas não é isso que estou procurando, pois em muitos casos não há realmente necessidade de compartilhamento e isso tornará as coisas menos eficientes.

A questão é como conseguir o seguinte:

permitir que a fábrica retorneunique_ptrpermitirunique_ptr desta classe para se tornar compartilhadopermitirshared_ptr dessa classe para obter cópias compartilhadas (viashared_from_this())evitar falhas quandounique_ptr dessa classe tenta ser compartilhado com isso (chamandoget_shared no exemplo acima)

Os itens 1 a 3 são preenchidos com o código acima,o problema está no item 4.

questionAnswers(6)

yourAnswerToTheQuestion