
Gavin Lambert wrote:
static std::unique_ptr<A> A::create(args...) noexcept
...
If you don't like the heap usage, the same concept applies if it returns an optional instead of a pointer (assuming it has a no-fail move).
With Boost.Outcome, it can be implemented exactly as above (including not letting an invalid instance escape), but *also* indicate a failure reason to the caller, through a simple change to the return type.
Following this train of thought to its logical conclusion is interesting. Suppose we need to copy. That would be unique_ptr<A> A::copy( A const & rhs, error_code & ec ) noexcept; because if construction can fail, copying most likely can fail, too. If we switch to optional, we'll have optional<A> A::create( error_code& ec ) noexcept; optional<A> A::copy( A const& rhs, error_code& ec ) noexcept; and then to result: result<A> A::create() noexcept; result<A> A::copy( A const& rhs ) noexcept; This implies that under this style of programming, a `result` is not copied with its copy constructor.