On Tue, Jun 13, 2017 at 1:28 AM, Gavin Lambert via Boost < boost@lists.boost.org> wrote:
On 13/06/2017 18:12, Emil Dotchevski wrote:
In Noexcept, it is not correct to always use try_, for the same reason you don't always use try with exception handling. That is only used if you want to _handle_ errors, not just check for errors; see the second Q&A here: https://zajo.github.io/boost-noexcept/#qanda.
Error checking with Noexcept depends on your choice of return type. For example, if your return type is T *, you'd check for 0, if your return type is shared_ptr<T> or optional<T>, you'd check using the conversion to bool.
Is it still legal to have a function return the designated error value without actually setting an error?
It could happen, but note that it has to be explicit: you have to actually return the invalid value, can't happen on its own. Similarly, you can pass 0 for std::error_code to something like outcome<T>. In fairness, the latter is perhaps more explicit, but it could still happen (I suppose, I may be wrong about this.) Regardless, the correct way to check for errors is to see if the result is valid. This is the price one must pay when not using exception handling.
Perhaps sometimes returning an empty shared_ptr is the successful return.
I can't imagine a function which returns shared_ptr<T> *and* which could fail, to return an empty one in case of success. That said, in that case all it means is that you can't use throw_ directly in a return expression; or you could partially specialize throw_return<> for a specific type of shared_ptr, if that's appropriate. In an earlier version I had the main throw_return template undefined, requiring users to specialize it to use throw_ in a function returning given type, but I got convinced that it is not worth it.
This in turn suggests that it's necessary to call try_ or similar to verify the difference between success and error, assuming that it does so using the TLS state rather than by inspecting the return value. (Or perhaps only inspects the TLS state when the return value is the error value, as a performance optimisation.)
try_ only inspects the TLS state. Similarly, try...catch also doesn't care about return values. Granted, if you throw you can't end up using an invalid value, but that's just the nature of the beast when you can't throw: you must check for bad results, and perhaps you should in some cases use a wrapper. I am not arguing against that, but it is a good thing that Noexcept doesn't require it, since a wrapper is almost certainly an overkill if you're returning, say, shared_ptr<T>.