All new code written henceforth ought to be designed around the C++ standard in my book, with hacks/workarounds as appropriate where the standard object falls short.
But otherwise regarding discussion of Outcome, I think there are three main use patterns for failure returning objects, and a single object design can't fulfill more than two of them at best.
You have never put it this way. Can you list the three use patterns here?
Sure. 1. User wants failure reason type to be local to only the code it applies to. So think custom E type, nonconvertible to any other E type, and E is never error_code nor exception_ptr. They specifically want to keep failure handling local a small patch of code e.g. constexpr evaluation contexts. All-narrow observers make sense for this use case as object usage is tightly integrated to the code using it, and failure is handled entirely locally. 2. User wants failure reason type to be globally understood and will be choosing either E = std::error_code, or E = std::exception_ptr. They specifically want failure handling to be able to traverse any or all code, just like C++ exception throws. This is where Outcome was primarily aimed at. All-wide observers make sense for this use case, as due to handling a wide degree of uncertainty, most failure handling code is *generic* i.e. we test for some specific failure causes, and for everything else we either ignore or hand it off to other code to handle. 3. User wants to write functional programming logic using the basic vocabulary of Maybe, Either and i/o monads and basic operators of bind, fmap, do etc and probably some subset or refinement of Hana for the collections monads, though my GSoC student may be making the Ranges TS a choice here as well later this summer. All-narrow observers make sense for this use case as the monadic operators ensure your function will never be called with the wrong state. Niall -- ned Productions Limited Consulting http://www.nedproductions.biz/ http://ie.linkedin.com/in/nialldouglas/