outcome v2.0-boost Release Notes

Release Date: 2018-01-18 // over 4 years ago
  • NOTE: Use the .tar.xz tarball attached, NOT the github generated ones, theirs are missing all the submodule dependencies

    ๐Ÿ”„ Changes since v1.0:

    As per the Boost peer review feedback, v2 Outcome has been pared down to
    no more than the barest of bare essentials. The plan is to participate
    ๐Ÿ“„ in a generalised C++ Monadic interface (P0650R0)
    ๐Ÿšš so all the monadic stuff is removed.

    Major changes:

    • You can now customise types directly, same as Expected, so result<T, EC = std::error_code> and outcome<T, EC = std::error_code, E = std::exception_ptr>.
    • Default construction no longer permitted, as per review feedback.
    • Empty state no longer possible, as per review feedback. Write
      optional<result<T, E>> if you want that.
    • As per review feedback, Variant storage gone, it's now a struct-based
      type for simplicity.
    • EC and E types are interpreted via trait::has_error_code_v<EC>
      ๐Ÿ‘ป and trait::has_exception_ptr_v<E>. This allows custom payloads to
      ๐Ÿ‘ป be easily attached to error_code and exception_ptr.
    • C interoperability is now available, and some C macros for
      working with struct result_TYPE are available in result.h.
    • Concepts TS is used when available, otherwise a partial
      SFINAE-based emulation is used.
    • Types EC and E must be default constructible. T need not
      be so.
    • Constructors now follow those of std::variant, so it will
      implicitly convert from any input constructible to any of its types so
      long as it is not ambiguous. As with std::variant, in place
      construction is achieved via in_place_type<T> tagging. Explicit
      conversion construction also works, we replicate std::variant's
      value semantics very closely despite not having variant storage.
    • New type sugar types success<T>, failure<EC, E> for being
      explicit about which kind of result or outcome we are constructing.
    • We implement construction from ValueOrError Concept matching
      types which include std::expected<T, E>, as per the ValueOrError
      paper https://wg21.link/P0786.
    • .has_value(), .has_error() and .has_exception() now only
      return true if that specific member is present. A new
      .has_failure() is true if errored or excepted.
    • .value() throws bad_result_access|bad_outcome_access
      or std::system_error(EC) or std::rethrow_exception(EC) or UB
      if no value or returns a reference to the value.
    • .error() throws bad_result_access|bad_outcome_access or UB if no
      error or returns a reference to the error.
    • .exception() throws bad_result_access|bad_outcome_access or UB if no
      ๐Ÿ‘ป exception or returns a reference to the exception.
    • .failure() returns the exception if present, else a synthesised
      ๐Ÿ‘ป exception_ptr from the error, else a null exception_ptr.
    • .assume_value(), .assume_error(), .assume_payload() and
      .assume_exception() all provide runtime unchecked UB access to the
      underlying storage.
    • The doxygen docs which were widely criticised have been replaced
      with an experimental Standardese + Hugo based solution instead.

    ๐Ÿšš Stuff removed:

    • Anything even faintly smelling of monads.
    • All the make_XXX() functions. The std::variant based constructor
      interface make them no longer necessary.
    • All preprocessor assembly of code fragments. You now have an
      equally complex rabbit warren of policy and trait driven composited
      fragments of template into implementation. I did warn reviewers during
      ๐Ÿ‘ the v1 review that a pure C++ v2 would be no better in this regard than
      the preprocessor assembled v1.
    • All macro based customisation points. We now use an ADL function
      based, or injection of type specialisation, customisation points. 100% C++.
    • error_code_extended is gone for now. It is believed that via the
      customisation points you can easily implement your own. There is
      a worked example at
    • Any operators apart from boolean test, strict equality and
      inequality comparison.
    • Any ability to change state after construction.
    • LEWG expected<T, E> is gone. The new checked<T, E>
      ๐Ÿ‘€ is a close substitute to Expected. See the FAQ entry on how to adapt
      a result<T, E> into an expected<T, E> with a simple shim class.

    Stuff retained:

    • OUTCOME_TRY, OUTCOME_TRYV, OUTCOME_TRYX all work as before.
    • noexcept propagation from types chosen works correctly.
    • Triviality of copy, move and destruction from types
      chosen is propagated correctly.
    • v1 unit test has been almost entirely ported over to v2 without
      much change other than what was needed. Porting v1 based code to v2
      should be 95% possible using find regex in files and replace.

    Stuff gained:

    • Type traits now work direct on all member functions. Member
      ๐Ÿšš variable traits are no longer necessary, and so have been removed.
    • Outcome v2 now conforms in every way to a typical STL vocabulary
      type. No unusual design tradeoffs or changes.

    Stuff lost:

    • Outcome v2 needs a much newer compiler than before: clang 4 or
      ๐Ÿ‘ better, GCC 6 or better, VS2017 or better. Ideally with Concepts
    • Compile time load may now be higher than with v1. In my own
      code, there is an approx 15% compile time regression in v2 over v1.