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
.