Avoiding extra move in make_unique/make_shared/emplace/etc for structures that use aggregate initialization

Instead of adding a constructor to your type that takes a factory function, instead create a new external factory object with a conversion operator to your type. With C++17, that takes minimal work:

template <class F>
struct factory {
    F f;

    operator invoke_result_t<F&>() { return f(); }
};

template <class F>
factory(F ) -> factory<F>;

For your earlier example, S doesn’t need the constrained constructor anymore. You would instead do:

optional<S> s;
s.emplace( factory{[]{ return foo(); }} ); // or really just factory{foo}

Which prints just ctor and dtor. Since we’re not modifying S in any way, we could use this in aggregates as well – like D.

Leave a Comment