basic_outcome<T, EC, EP, NoValuePolicy> - Boost.Outcome documentation

# `basic_outcome<T, EC, EP, NoValuePolicy>`

A type carrying one of (i) a successful `T` (ii) a disappointment `EC` (iii) a failure `EP` (iv) both a disappointment `EC` and a failure `EP`, with `NoValuePolicy` specifying what to do if one tries to read state which isn’t there. Any one, two, or all of `T`, `EC` and `EP` can be `void` to indicate no value for that state is present. Detectable using `is_basic_outcome<T>` .

Requires: Concept requirements if C++ 20, else static asserted:

- That trait `type_can_be_used_in_basic_result<R>` is true for `T`, `EC` and `EP`.
- That either `EC` is `void` or `DefaultConstructible`.
- That either `EP` is `void` or `DefaultConstructible`.

Namespace: `BOOST_OUTCOME_V2_NAMESPACE`

Header: `<boost/outcome/basic_outcome.hpp>`

Inclusions: The very lightest weight of C and C++ header files:

1. `<cstdint>`
2. `<initializer_list>`
3. `<iosfwd>`
4. `<new>`
5. `<type_traits>`
6. If `BOOST_OUTCOME_USE_STD_IN_PLACE_TYPE` is `1`, `<utility>` (defaults to `1` for C++ 17 or later only)
7. If C++ exceptions disabled and `BOOST_OUTCOME_DISABLE_EXECINFO` undefined only (used to print stack backtraces on “exception throw”):
   1. `<sal.h>` (Windows only)
   2. `<stddef.h>` (Windows only)
   3. `<string.h>` (Windows only)
   4. `<execinfo.h>` (POSIX only)
8. `<cstdio>`
9. `<cstdlib>`
10. `<cassert>`

This very light weight set of inclusion dependencies makes basic outcome suitable for use in global header files of very large C++ codebases.

### Design rationale

`basic_outcome` extends `basic_result<T, E, NoValuePolicy>` with a third state to transport, conventionally (but not necessarily) some sort of “abort” or “exceptional” state which a function can return to indicate that not only did the operation fail, but it did so catastrophically i.e. please abort any attempt to retry the operation.

A perfect alternative is to throw a C++ exception for the abort code path, and indeed most programs ought to do exactly that instead of using `basic_outcome`. However there are a number of use cases where choosing `basic_outcome` shines:

1. Where C++ exceptions or RTTI is not available, but the ability to fail catastrophically without terminating the program is important.
2. Where deterministic behaviour is required even in the catastrophic failure situation.
3. In unit test suites of code using Outcome it is extremely convenient to accumulate test failures into a `basic_outcome` for later reporting. A similar convenience applies to RPC situations, where C++ exception throws need to be accumulated for reporting back to the initiating endpoint.
4. Where a function is “dual use deterministic” i.e. it can be used deterministically, in which case one switches control flow based on `.error()`, or it can be used non-deterministically by throwing an exception perhaps carrying a custom payload.

### Public member type aliases

- `value_type` is `T`.
- `error_type` is `EC`.
- `exception_type` is `EP`.
- `value_type_if_enabled` is `T` if construction from `T` is available, else it is a usefully named unusable internal type.
- `error_type_if_enabled` is `EC` if construction from `EC` is available, else it is a usefully named unusable internal type.
- `exception_type_if_enabled` is `EP` if construction from `EP` is available, else it is a usefully named unusable internal type.
- `rebind<A, B = EC, C = EP, D = NoValuePolicy>` is `basic_outcome<A, B, C, D>`.

### Protected member predicate booleans

- `predicate::constructors_enabled` is constexpr boolean true if:

  1. Decayed `value_type` and decayed `error_type` are not the same type, or both are `void`.
  2. Decayed `value_type` and decayed `exception_type` are not the same type, or both are `void`.
  3. Decayed `error_type` and decayed `exception_type` are not the same type, or both are `void`.

- `predicate::implicit_constructors_enabled` is constexpr boolean true if:

  1. `predicate::constructors_enabled` is true.
  2. Trait `is_error_type<E>` is not true for both decayed `value_type` and decayed `error_type` at the same time.
  3. `value_type` is not implicitly constructible from `error_type` and `error_type` is not implicitly constructible from `value_type`.
     OR
     trait `is_error_type<E>` is true for decayed `error_type` and `error_type` is not implicitly constructible from `value_type` and `value_type` is an integral type.
  4. `value_type` is not implicitly constructible from `exception_type`.
  5. `error_type` is not implicitly constructible from `exception_type`.
  6. `exception_type` is not implicitly constructible from `value_type`.
  7. `exception_type` is not implicitly constructible from `error_type`.

- `predicate::enable_value_converting_constructor<A>` is constexpr boolean true if:

  1. `predicate::constructors_enabled` is true.
  2. Decayed `A` is not this `basic_outcome` type.
  3. `predicate::implicit_constructors_enabled` is true.
  4. Decayed `A` is not an `in_place_type_t`.
  5. Trait `is_error_type_enum<E, Enum>` is false for `error_type` and decayed `A`.
  6. `value_type` is implicitly constructible from `A` and `error_type` is not implicitly constructible from `A`.
     OR
     `value_type` is the exact same type as decayed `A` and `value_type` is implicitly constructible from `A`.
  7. `exception_type` is not implicitly constructible from `A`.

- `predicate::enable_error_converting_constructor<A>` is constexpr boolean true if:

  1. `predicate::constructors_enabled` is true.
  2. Decayed `A` is not this `basic_outcome` type.
  3. `predicate::implicit_constructors_enabled` is true.
  4. Decayed `A` is not an `in_place_type_t`.
  5. Trait `is_error_type_enum<E, Enum>` is false for `error_type` and decayed `A`.
  6. `value_type` is not implicitly constructible from `A` and `error_type` is implicitly constructible from `A`.
     OR
     `error_type` is the exact same type as decayed `A` and `error_type` is implicitly constructible from `A`.
  7. `exception_type` is not implicitly constructible from `A`.

- `predicate::enable_error_condition_converting_constructor<ErrorCondEnum>` is constexpr boolean true if:

  1. `predicate::constructors_enabled` is true.
  2. Decayed `ErrorCondEnum` is not this `basic_outcome` type.
  3. Decayed `ErrorCondEnum` is not an `in_place_type_t`.
  4. Trait `is_error_type_enum<E, Enum>` is true for `error_type` and decayed `ErrorCondEnum`.
  5. `exception_type` is not implicitly constructible from `ErrorCondEnum`.

- `predicate::enable_exception_converting_constructor<A>` is constexpr boolean true if:

  1. `predicate::constructors_enabled` is true.
  2. Decayed `A` is not this `basic_outcome` type.
  3. `predicate::implicit_constructors_enabled` is true.
  4. Decayed `A` is not an `in_place_type_t`.
  5. `value_type` is not implicitly constructible from `A`.
  6. `error_type` is not implicitly constructible from `A`.
  7. `exception_type` is implicitly constructible from `A`.

- `predicate::enable_error_exception_converting_constructor<A, B>` is constexpr boolean true if:

  1. `predicate::constructors_enabled` is true.
  2. Decayed `A` is not this `basic_outcome` type.
  3. `predicate::implicit_constructors_enabled` is true.
  4. Decayed `A` is not an `in_place_type_t`.
  5. `value_type` is not implicitly constructible from `A`.
  6. `error_type` is implicitly constructible from `A`.
  7. `value_type` is not implicitly constructible from `B`.
  8. `exception_type` is implicitly constructible from `B`.

- `predicate::enable_compatible_conversion<A, B, C, D>` is constexpr boolean true if:

  1. `predicate::constructors_enabled` is true.
  2. `basic_outcome<A, B, C, D>` is not this `basic_outcome` type.
  3. `A` is `void` OR `value_type` is explicitly constructible from `A`.
  4. `B` is `void` OR `error_type` is explicitly constructible from `B`.
  5. `C` is `void` OR `exception_type` is explicitly constructible from `C`.

- `predicate::enable_inplace_value_constructor<Args...>` is constexpr boolean true if:

  1. `predicate::constructors_enabled` is true.
  2. `value_type` is `void` OR `value_type` is explicitly constructible from `Args...`.

- `predicate::enable_inplace_error_constructor<Args...>` is constexpr boolean true if:

  1. `predicate::constructors_enabled` is true.
  2. `error_type` is `void` OR `error_type` is explicitly constructible from `Args...`.

- `predicate::enable_inplace_exception_constructor<Args...>` is constexpr boolean true if:

  1. `predicate::constructors_enabled` is true.
  2. `exception_type` is `void` OR `exception_type` is explicitly constructible from `Args...`.

- `predicate::enable_inplace_value_error_exception_constructor<Args...>` is constexpr boolean true if:

  1. `predicate::constructors_enabled` is true.
  2. `predicate::implicit_constructors_enabled` is true.
  3. Exactly one of `value_type` is explicitly constructible from `Args...`, or `error_type` is explicitly constructible from `Args...`, or `exception_type` is explicitly constructible from `Args...`.

#### Summary of standard requirements provided

- `DefaultConstructible`, always deleted to force user to choose valued or errored or excepted for every outcome instanced.
- `MoveConstructible`, if all of `value_type`, `error_type` and `exception_type` implement move constructors.
- `CopyConstructible`, if all of `value_type`, `error_type` and `exception_type` implement copy constructors.
- `MoveAssignable`, if all of `value_type`, `error_type` and `exception_type` implement move constructors and move assignment.
- `CopyAssignable`, if all of `value_type`, `error_type` and `exception_type` implement copy constructors and copy assignment.
- `Destructible`.
- `TriviallyCopyable`, if all of `value_type`, `error_type` and `exception_type` are trivially copyable.
- `TrivialType`, if all of `value_type`, `error_type` and `exception_type` are trivial types.
- `LiteralType`, if all of `value_type`, `error_type` and `exception_type` are literal types.

- `StandardLayoutType`. It is implementation defined if `basic_outcome` can be used by C. However all of the three major compilers MSVC, GCC and clang implement C layout of `basic_outcome` as follows:

      struct outcome_layout {
        struct result_layout {
          value_type value;
          unsigned int flags;
          error_type error;
        };
        exception_type exception;
      };

  If you choose standard layout `value_type`, `error_type` and `exception_type`, `basic_outcome` works fine from C on MSVC, GCC and clang.

- `EqualityComparable`, if all of `value_type`, `error_type` and `exception_type` implement equality comparisons with one another.

- `LessThanComparable`, not implemented due to availability of implicit conversions from `value_type`, `error_type` and `exception_type`, this can cause major surprise (i.e. hard to diagnose bugs), so we don’t implement these at all. ~ `Swappable`

- `Hash`, not implemented as a generic implementation of a unique hash for non-valued items which are unequal would require a dependency on RTTI being enabled.

Thus `basic_outcome` meets the `Regular` concept if all of `value_type`, `error_type` and `exception_type` are `Regular`, except for the lack of a default constructor. Often where one needs a default constructor, wrapping `basic_outcome` into `std::optional<T>` will suffice.

### Public member functions

#### Disabling constructors

1. `basic_outcome(Args...) = delete`

   Disabling catchall constructor used to give useful diagnostic error when trying to use non-inplace constructors when `predicate::constructors_enabled` is false.

2. `basic_outcome(X &&) = delete`

   Disabling implicit constructor used to give useful diagnostic error when trying to use implicit constructors when `predicate::implicit_constructors_enabled` is false.

#### Copy and move constructors and assignment, and destructor

1. `basic_outcome() = delete`

   The default constructor (disabled).

2. `basic_outcome(basic_outcome &&)`

   Move constructor. Constexpr, triviality and noexcept propagating.

3. `basic_outcome(const basic_outcome &)`

   Copy constructor. Constexpr, triviality and noexcept propagating.

4. `basic_outcome &operator=(basic_outcome &&)`

   Move assignment. Constexpr, triviality and noexcept propagating.

5. `basic_outcome &operator=(const basic_outcome &)`

   Copy assignment. Constexpr, triviality and noexcept propagating.

6. `~basic_outcome()`

   Destructor. Constexpr, triviality and noexcept propagating.

#### Converting constructors

1. `basic_outcome(R &&)`

   Implicit `value_type` constructor. Available if `predicate::enable_value_converting_constructor<R>` is true. Constexpr, triviality and noexcept propagating.

2. `basic_outcome(S &&)`

   Implicit `error_type` constructor. Available if `predicate::enable_error_converting_constructor<S>` is true. Constexpr, triviality and noexcept propagating.

3. `basic_outcome(ErrorCondEnum &&)`

   Implicit `error_type` from `ErrorCondEnum` constructor. Available if `predicate::enable_error_condition_converting_constructor<ErrorCondEnum>` is true. Constexpr, triviality and noexcept propagating.

4. `basic_outcome(P &&)`

   Implicit `exception_type` constructor. Available if `predicate::enable_exception_converting_constructor<P>` is true. Constexpr, triviality and noexcept propagating.

5. `basic_outcome(S &&, P &&)`

   Implicit `error_type` + `exception_type` constructor. Available if `predicate::enable_error_exception_converting_constructor<S, P>` is true. Constexpr, triviality and noexcept propagating.

6. `explicit basic_outcome(ValueOrError<T, E> &&)`

   Explicit converting constructor from `ValueOrError<T, E>` concept matching types. Available if `convert::value_or_error<>` permits it. Constexpr, triviality and noexcept propagating.

7. `explicit basic_outcome(const basic_outcome<A, B, C, D> &)`

   Explicit converting copy constructor from compatible `basic_outcome`. Available if `predicate::enable_compatible_conversion<A, B, C, D>` is true. Constexpr, triviality and noexcept propagating.

8. `explicit basic_outcome(basic_outcome<A, B, C, D> &&)`

   Explicit converting move constructor from compatible `basic_outcome`. Available if `predicate::enable_compatible_conversion<A, B, C, D>` is true. Constexpr, triviality and noexcept propagating.

9. `explicit basic_outcome(const basic_result<A, B, C> &)`

   Explicit converting copy constructor from compatible `basic_result`. Available if `predicate::enable_compatible_conversion<A, B, void, C>` is true. Constexpr, triviality and noexcept propagating.

10. `explicit basic_outcome(basic_result<A, B, C> &&)`

    Explicit converting move constructor from compatible `basic_result`. Available if `predicate::enable_compatible_conversion<A, B, void, C>` is true. Constexpr, triviality and noexcept propagating.

#### Inplace constructors

1. `explicit basic_outcome(in_place_type_t<value_type_if_enabled>, Args ...)`

   Explicit inplace value constructor. Available if `predicate::enable_inplace_value_constructor<Args ...>` is true. Constexpr, triviality and noexcept propagating.

2. `explicit basic_outcome(in_place_type_t<value_type_if_enabled>, std::initializer_list<U>, Args ...)`

   Explicit inplace value constructor. Available if `predicate::enable_inplace_value_constructor<std::initializer_list<U>, Args ...>` is true. Constexpr, triviality and noexcept propagating.

3. `explicit basic_outcome(in_place_type_t<error_type_if_enabled>, Args ...)`

   Explicit inplace error constructor. Available if `predicate::enable_inplace_error_constructor<Args ...>` is true. Constexpr, triviality and noexcept propagating.

4. `explicit basic_outcome(in_place_type_t<error_type_if_enabled>, std::initializer_list<U>, Args ...)`

   Explicit inplace error constructor. Available if `predicate::enable_inplace_error_constructor<std::initializer_list<U>, Args ...>` is true. Constexpr, triviality and noexcept propagating.

5. `explicit basic_outcome(in_place_type_t<exception_type_if_enabled>, Args ...)`

   Explicit inplace exception constructor. Available if `predicate::enable_inplace_exception_constructor<Args ...>` is true. Constexpr, triviality and noexcept propagating.

6. `explicit basic_outcome(in_place_type_t<exception_type_if_enabled>, std::initializer_list<U>, Args ...)`

   Explicit inplace exception constructor. Available if `predicate::enable_inplace_exception_constructor<std::initializer_list<U>, Args ...>` is true. Constexpr, triviality and noexcept propagating.

7. `basic_outcome(A1 &&, A2 &&, Args ...)`

   Implicit inplace value or error or exception constructor. Available if `predicate::enable_inplace_value_error_exception_constructor<A1, A2, Args ...>` is true. Constexpr, triviality and noexcept propagating.

#### Tagged constructors

1. `basic_outcome(const success_type<T> &)`

   Implicit value-from-success-type-sugar copy constructor. Available if `predicate::enable_compatible_conversion<T, void, void>` is true, or `T` is `void`. Constexpr, triviality and noexcept propagating.

2. `basic_outcome(success_type<T> &&)`

   Implicit value-from-success-type-sugar move constructor. Available if `predicate::enable_compatible_conversion<T, void, void>` is true, or `T` is `void`. Constexpr, triviality and noexcept propagating.

3. `basic_outcome(const failure_type<EC> &)`

   Implicit error-from-failure-type-sugar copy constructor. Available if `predicate::enable_compatible_conversion<void, EC, void, void>` is true. Constexpr, triviality and noexcept propagating.

4. `basic_outcome(failure_type<EC> &&)`

   Implicit error-from-failure-type-sugar move constructor. Available if `predicate::enable_compatible_conversion<void, EC, void, void>` is true. Constexpr, triviality and noexcept propagating.

5. `basic_outcome(const failure_type<EP> &)`

   Implicit exception-from-failure-type-sugar copy constructor. Available if `predicate::enable_compatible_conversion<void, void, EP, void>` is true. Constexpr, triviality and noexcept propagating.

6. `basic_outcome(failure_type<EP> &&)`

   Implicit exception-from-failure-type-sugar move constructor. Available if `predicate::enable_compatible_conversion<void, void, EP, void>` is true. Constexpr, triviality and noexcept propagating.

7. `basic_outcome(const failure_type<EC, EP> &)`

   Implicit error-and-exception-from-failure-type-sugar copy constructor. Available if `predicate::enable_compatible_conversion<void, EC, EP, void>` is true. Constexpr, triviality and noexcept propagating.

8. `basic_outcome(failure_type<EC, EP> &&)`

   Implicit error-and-exception-from-failure-type-sugar move constructor. Available if `predicate::enable_compatible_conversion<void, EC, EP, void>` is true. Constexpr, triviality and noexcept propagating.

#### Observers

1. `explicit operator bool() const noexcept`

   Returns true if a value is present. Constexpr, never throws.

2. `bool has_value() const noexcept`

   Returns true if a value is present. Constexpr, never throws.

3. `bool has_error() const noexcept`

   Returns true if an error is present. Constexpr, never throws.

4. `bool has_exception() const noexcept`

   Returns true if an exception is present. Constexpr, never throws.

5. `bool has_failure() const noexcept`

   Returns true if there is either an error or an exception. Constexpr, never throws.

6. `value_type &assume_value() & noexcept`

   Narrow contract lvalue reference observer of any value present. Constexpr propagating, never throws.

7. `const value_type &assume_value() const & noexcept`

   Narrow contract const lvalue reference observer of any value present. Constexpr propagating, never throws.

8. `value_type &&assume_value() && noexcept`

   Narrow contract rvalue reference observer of any value present. Constexpr propagating, never throws.

9. `const value_type &&assume_value() const && noexcept`

   Narrow contract const rvalue reference observer of any value present. Constexpr propagating, never throws.

10. `value_type &value() &`

    Wide contract lvalue reference observer of any value present. Constexpr propagating.

11. `const value_type &value() const &`

    Wide contract const lvalue reference observer of any value present. Constexpr propagating.

12. `value_type &&value() &&`

    Wide contract rvalue reference observer of any value present. Constexpr propagating.

13. `const value_type &&value() const &&`

    Wide contract const rvalue reference observer of any value present. Constexpr propagating.

14. `error_type &assume_error() & noexcept`

    Narrow contract lvalue reference observer of the stored error. Constexpr propagating, never throws.

15. `const error_type &assume_error() const & noexcept`

    Narrow contract const lvalue reference observer of the stored error. Constexpr propagating, never throws.

16. `error_type &&assume_error() && noexcept`

    Narrow contract rvalue reference observer of the stored error. Constexpr propagating, never throws.

17. `const error_type &&assume_error() const && noexcept`

    Narrow contract const rvalue reference observer of the stored error. Constexpr propagating, never throws.

18. `error_type &error() &`

    Wide contract lvalue reference observer of the stored error. Constexpr propagating.

19. `const error_type &error() const &`

    Wide contract const lvalue reference observer of the stored error. Constexpr propagating.

20. `error_type &&error() &&`

    Wide contract rvalue reference observer of the stored error. Constexpr propagating.

21. `const error_type &&error() const &&`

    Wide contract const rvalue reference observer of the stored error. Constexpr propagating.

22. `exception_type &assume_exception() & noexcept`

    Narrow contract lvalue reference observer of the stored exception. Constexpr propagating, never throws.

23. `const exception_type &assume_exception() const & noexcept`

    Narrow contract const lvalue reference observer of the stored exception. Constexpr propagating, never throws.

24. `const exception_type &&assume_exception() const && noexcept`

    Narrow contract const rvalue reference observer of the stored exception. Constexpr propagating, never throws.

25. `exception_type &&assume_exception() && noexcept`

    Narrow contract rvalue reference observer of the stored exception. Constexpr propagating, never throws.

26. `exception_type &exception() &`

    Wide contract lvalue reference observer of the stored exception. Constexpr propagating.

27. `const exception_type &exception() const &`

    Wide contract const lvalue reference observer of the stored exception. Constexpr propagating.

28. `exception_type &&exception() &&`

    Wide contract rvalue reference observer of the stored exception. Constexpr propagating.

29. `const exception_type &&exception() const &&`

    Wide contract const rvalue reference observer of the stored exception. Constexpr propagating.

30. `exception_type failure() const noexcept`

    Synthesising observer of the stored exception or error. Available if the traits `is_error_code_available<T>` and `is_exception_ptr_available<T>` are both true. Never throws.

31. `failure_type<error_type, exception_type> as_failure() const &`

    Return the output from free function `failure()` containing a copy of any errored and/or excepted state.

#### Modifiers

1. `void swap(basic_outcome &)`

   Swap one basic_outcome with another, with the strong guarantee. Noexcept propagating.

2. `failure_type<error_type, exception_type> as_failure() &&`

   Return the output from free function `failure()` containing a move of any errored and/or excepted state.

#### Comparisons

See above for why `LessThanComparable` is not implemented.

1. `bool operator==(const basic_result<A, B, C> &) const`

   Returns true if this outcome compares equal to the other result. Constexpr and noexcept propagating.

2. `bool operator==(const basic_outcome<A, B, C, D> &) const`

   Returns true if this outcome compares equal to the other outcome. Constexpr and noexcept propagating.

3. `bool operator==(const success_type<A> &) const`

   Returns true if this result compares equal to the success type sugar. Constexpr and noexcept propagating.

4. `bool operator==(const failure_type<A, B> &) const`

   Returns true if this outcome compares equal to the failure type sugar. Constexpr and noexcept propagating.

5. `bool operator!=(const basic_result<A, B, C> &) const`

   Returns true if this outcome does not compare equal to the other result. Constexpr and noexcept propagating.

6. `bool operator!=(const basic_outcome<A, B, C, D> &) const`

   Returns true if this outcome does not compare equal to the other outcome. Constexpr and noexcept propagating.

7. `bool operator!=(const success_type<A> &) const`

   Returns true if this outcome does not compare equal to the success type sugar. Constexpr and noexcept propagating.

8. `bool operator!=(const failure_type<A, B> &) const`

   Returns true if this outcome does not compare equal to the failure type sugar. Constexpr and noexcept propagating.

Last revised: February 01, 2019 at 23:42:52 UTC