On Mon, Jun 12, 2017 at 4:01 PM, Niall Douglas via Boost < boost@lists.boost.org> wrote:
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.
Okay.
Relying on TLS trickery hides control flow paths.
How? Which control path is hidden by a return throw_(error())?
And if people fail to write the check, errors get lost or pop out in the wrong locations.
So, use optional<> with Noexcept.
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.
Yes, I understand the argument for a wrapper type, what I've demonstrated is that this is a separate issue. Yes, do use a wrapper type if it is appropriate for the reasons you're providing.
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.
The rationale is that this is a better design choice for C++, or else you're arguing that C++ exception handling, which also doesn't burden return values with having to transport errors, is a bad design choice.