Tuesday, 15 July 2014

c++ - How would you use Alexandrescu's Expected with void functions? -



c++ - How would you use Alexandrescu's Expected<T> with void functions? -

so ran across (imho) nice thought of using composite construction of homecoming value , exception - expected<t>. overcomes many shortcomings of traditional methods of error handling (exceptions, error codes).

see andrei alexandrescu's talk (systematic error handling in c++) , its slides.

the exceptions , error codes have same usage scenarios functions homecoming , ones don't. expected<t>, on other hand, seems targeted @ functions homecoming values.

so, questions are:

have of tried expected<t> in practice? how apply idiom functions returning nil (that is, void functions)?

update:

i guess should clarify question. expected<void> specialization makes sense, i'm more interested in how used - consistent usage idiom. implementation secondary (and easy).

for example, alexandrescu gives illustration (a bit edited):

string s = readline(); auto x = parseint(s).get(); // throw on error auto y = parseint(s); // won’t throw if (!y.valid()) { // ... }

this code "clean" in way flows naturally. need value - it. however, expected<void> 1 have capture returned variable , perform operation on (like .throwiferror() or something), not elegant. , obviously, .get() doesn't create sense void.

so, code if had function, toupper(s), modifies string in-place , has no homecoming value?

have of tried expected; in practice?

it's quite natural, used before saw talk.

how apply idiom functions returning nil (that is, void functions)?

the form presented in slides has subtle implications:

the exception bound value. it's ok handle exception wish. if value ignored reasons, exception suppressed.

this not hold if have expected<void>, because since nobody interested in void value exception ignored. forcefulness force reading expected<t> in alexandrescus class, assertions , explicit suppress fellow member function. rethrowing exception destructor not allowed reasons, has done assertions.

template <typename t> struct expected; #ifdef ndebug // no asserts template <> class expected<void> { std::exception_ptr spam; public: template <typename e> expected(e const& e) : spam(std::make_exception_ptr(e)) {} expected(expected&& o) : spam(std::move(o.spam)) {} expected() : spam() {} bool valid() const { homecoming !spam; } void get() const { if (!valid()) std::rethrow_exception(spam); } void suppress() {} }; #else // asserts, check if homecoming value checked // if assertions succeed, other code right // note: not write "assert(expected.valid());" template <> class expected<void> { std::exception_ptr spam; mutable std::atomic_bool read; // threadsafe public: template <typename e> expected(e const& e) : spam(std::make_exception_ptr(e)), read(false) {} expected(expected&& o) : spam(std::move(o.spam)), read(o.read.load()) {} expected() : spam(), read(false) {} bool valid() const { read=true; homecoming !spam; } void get() const { if (!valid()) std::rethrow_exception(spam); } void suppress() { read=true; } ~expected() { assert(read); } }; #endif expected<void> calculate(int i) { if (!i) homecoming std::invalid_argument("i must non-null"); homecoming {}; } int main() { calculate(0).suppress(); // suppressing must explicit if (!calculate(1).valid()) homecoming 1; calculate(5); // assert fails }

c++ c++11 error-handling runtime-error

No comments:

Post a Comment