my comment in reply to martin_sustrik.
I wanted to post some code into the comment but I finally gave up. I will post it here instead. Disclaimer: this code has not been compiled.
class foo { public: ~foo() {} foo(foo&& other) { guts.a = std::move(other.a); // no-fail } foo& operator=(foo other) { // no-fail using std::swap; swap(guts.a, other.guts.a); return *this; } static optional<foo> init() { optional<foo> result; type guts = {}; // ~type() cleans up on exit guts.a.reset(new(std::nothrow) int(5)); if (!guts.a) {return result;} // no foo constructed result.reset(foo(guts)); //no-fail move construction return std::move(result); // no-fail move of result } int do() {return guts.a.get();} // a cannot be empty private: struct type { std::unique_ptr<int> a; }; type guts; foo(); // disabled foo(const foo&); // disabled foo(type&& gutsArg) {guts.a = std::move(gutsArg.a);} // no-fail }; auto MyFoo = foo::init(); if (!MyFoo) return; MyFoo->do();
if you want to return a detailed error from init()
change init()
to return a tuple:
static std::tuple<error, optional<foo>> init();and use tie to break the result into local vars:
optional<foo> MyFoo; error MyError; std::tie(MyError, MyFoo) = foo::init();