In the noexcept case, what happens in the Error-Handling function if the error_id generated by the Error-Reporting function is lost by the intermediate functions?
On Mon, May 25, 2020 at 7:34 AM Bjorn Reese via Boost
In the noexcept case, what happens in the Error-Handling function if the error_id generated by the Error-Reporting function is lost by the intermediate functions?
You mean, as in: leaf::result<float> f(); // Returns a float or an error leaf::result<int> g() // Returns an int or an error { (void) f(); // Discard the float or the error returned by f return 42; } void error_handler() { leaf::try_handle_all( [ ] { LEAF_AUTO(answer, g()); .... // Success! Use answer. }, .... // Handle errors ); // Done handling errors, the context in the scope of try_handle_all is destroyed. } At the time control returns back to our error_handler, any error objects that were passed by f to LEAF are stored in a context (or, in case there weren't any error handlers that need them, were discarded on the spot). When the context in the scope of leaf::try_handle_all is destroyed, its contents are destroyed as well. To access an error object when handling errors, you need the correct error_id. Had g reported another failure after discarding whatever f returned, when that error reaches our error_handler, if the context still contains any error objects associated with the error_id g discarded, they can't be accessed because the new error has a different error_id. You get a unique error_id when you call leaf::new_error. It's like a serial number of this particular failure. You can print error_ids in diagnostic messages; this can help detect bugs where a failure was erroneously discarded (not handled).
On 2020-05-25 22:21, Emil Dotchevski via Boost wrote:
You mean, as in:
Good example.
leaf::result<float> f(); // Returns a float or an error
leaf::result<int> g() // Returns an int or an error { (void) f(); // Discard the float or the error returned by f return 42; }
Suppose there is also an h() function in the call stack that is being called by the error_handler() function instead of g(): leaf::result<int> h() { auto res = g(); // How to detect that f() raised an error without knowing // its error_id? return res; } Can this function detect that someone further up the call stack has already raised an error? Similar to std::uncaught_exceptions()?
On Tue, May 26, 2020 at 2:53 PM Bjorn Reese via Boost
On 2020-05-25 22:21, Emil Dotchevski via Boost wrote:
You mean, as in:
Good example.
leaf::result<float> f(); // Returns a float or an error
leaf::result<int> g() // Returns an int or an error { (void) f(); // Discard the float or the error returned by f return 42; }
Suppose there is also an h() function in the call stack that is being called by the error_handler() function instead of g():
leaf::result<int> h() { auto res = g(); // How to detect that f() raised an error without knowing // its error_id? return res; }
Can this function detect that someone further up the call stack has already raised an error? Similar to std::uncaught_exceptions()?
If g() still does (void) f(); (that is, discards the error), by analogy this is like try { f(); } catch(...) { }, so I don't understand why h() would care. That said, you can detect that f() reported an error. This is exposed through the augment_id API: https://zajo.github.io/leaf/#augment_id. You can instantiate this class, and then later call check_error() to see if some function (from this thread) has reported any errors since then: leaf::augment_id id; (void) f(); (void) g(); if( id.check_error() ) { // f() or g(), or something they call, reported at least one error. // The error(s) may have been discarded or handled. } Naturally, this is not common. Generally, we handle, rather than discard, all reported errors.
participants (2)
-
Bjorn Reese
-
Emil Dotchevski