2017-06-13 7:54 GMT+02:00 Vicente J. Botet Escriba via Boost < boost@lists.boost.org>:
Le 13/06/2017 à 01:01, Niall Douglas via Boost a écrit :
Still, I fail to see how Noexcept differs from Outcome in this aspect.
Semantically the only difference is that Noexcept doesn't force users to use a special template in return types, but that's a good thing. If it's preferable, they can still use a special template, and if they do, it's trivial to design because it doesn't have to transport errors -- Noexcept takes care of that for you.
You *want* APIs to clearly indicate their failure contract.
Relying on TLS trickery hides control flow paths. And if people fail to write the check, errors get lost or pop out in the wrong locations.
Forcing a wrapper type to be used also allows [[nodiscard]] to be leveraged, and in the future static analysis to be applied. Neither works with your scheme, which is why I rejected it very early on.
Finally, Rust and Swift have adopted a Result
model. It is generally viewed as a good design choice for its problem domain. Varying significantly from what the other system languages are doing needs to have very strong rationale. AFAIK [1], the proposed library and Swift error handling mechanism are very close. Swift has alternatively also used Result
as we could have expected . The main difference I see is that one is library based and the other language based.
In Swift you signal that a function can throw adding throws() to the signature. Swift has builtin optionals and adding throw is almost like declaring it to return T? (optional<T>.
You cannot call this function without using try, try! or try?
IIUC, with Noexcept, you cannot require this as it is a library. However when the user uses try_ it is able to control whether the call succeeds or fails.
In order to force it, the closer is to use a return type that tell you that there could be errors, as return_<T>.
I will say that if Noexcept required this return_<T> type, it will be like outcome<T>, except that the error is transported using TLS instead of using the stack (please let me know if I'm wrong)
However if Noexcept doesn't require a return_<T> then it is much difficult to force the use of the try functions. But it works yet.
I see advantages in this approach and I don't know which one is more efficient in the success and failure cases. Some measures will be more than welcome.
I'll rename Noexcept to ErrorTLS
In summary,
do we want an error handling mechanism in C++ based on Swift error handling ;-) ? Do we want a library that emulates it as Boost.Noexcept in Boost?
do we want a monadic error handling in C++ as Result
in Boost? do we want both in Boost?
I believe both merit to be tried
I agree with everything here. You have probably put it better than me. Regards, &rzej;