make_shared (and make_unique) for classes with private constructors

A common idiom is to have a privately constructable class with a (static) factory that returns a shared (or unique) pointer.

class A {
    A() {};

public:
    static std::shared_ptr<A> make() {
        return std::make_shared<A>();
    }
};
Looks simple and yet doesn't work since std::make_shared cannot access A's constructor.

I found a simple trick how to solve this without opening the class up to public construction: add a parameter with a private »cookie« to the constructor which proves that the class is being constructed »from within«.

class A {
    struct ctor_cookie {};

public:
    explicit A(ctor_cookie) {};
    static std::shared_ptr<A> make() {
        return std::make_shared<A>(ctor_cookie());
    }
};

Comments

  1. Nice idea! However, it creates a public ctor that just looks a bit weird in the API... With this technique, there is probably no way around this, I guess.

    ReplyDelete
  2. This is a neat trick, but `A` can still be constructed with `A{{}}` since `ctor_cookie` is aggregate constructible. You'll want to make `ctor_cookie` have a more unique and probably explicit constructor than this. See this link on compiler explorer for a demonstration: https://gcc.godbolt.org/z/roTsx4

    ReplyDelete
  3. Trading News This is a good post. This post gives truly quality information. I’m definitely going to look into it. Really very useful tips are provided here. Thank you so much. Keep up the good works

    ReplyDelete
  4. http://www.robert-puskas.info/2018/10/lod-using-make-shared-unique-with-private-constructors.html

    ReplyDelete

Post a Comment