Boost C++ Libraries of the most highly regarded and expertly designed C++ library projects in the world. Herb Sutter and Andrei Alexandrescu, C++ Coding Standards

This is the documentation for an old version of Boost. Click here to view this page for the latest version.

Outcome 2.1 library

Niall Douglas

Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at

Table of Contents

Build and install
Error codes
Plugging a library into std::error_code`
Plugging a library into boost::system::error_code
Narrow contracts
ASIO/Networking TS : Boost < 1.70
ASIO/Networking TS: Boost >= 1.70
The main advantages
Approximate map between error code designs
Major differences
status_result and status_outcome
Worked example: Custom domain
Tying it all together
Using Outcome from C code
API reference
Frequently asked questions


Outcome is a set of tools for reporting and handling function failures in contexts where directly using C++ exception handling is unsuitable. Such contexts include:

Outcome addresses failure handling through returning a special type from functions, which is able to store either a successfully computed value (or void), or the information about failure. Outcome also comes with a set of idioms for dealing with such types.

Particular care has been taken to ensure that Outcome has the lowest possible impact on build times, thus making it suitable for use in the global headers of really large codebases. Storage layout is guaranteed and is C-compatible for result<T, E>1, thus making Outcome based code long term ABI-stable.


Ben Craig’s work on P1886 Error speed benchmarking has led to a better_optimisation branch intended to be merged end of 2020 as Outcome v2.2.0, after twelve months of testing. This branch has a number of major and breaking changes to Outcome v2:

  1. A new trait is_move_bitcopying<T> is added, which opts types into a library-based emulation of P1029 move = bitcopies. Experimental std::error is opted in by default. If this trait is true for your T or E type, Outcome will track moved-from status for your type, and will only call your type’s destructor if it was not moved from. If your compiler’s optimiser is sufficiently able to fold code, this improves codegen quality for Experimental Outcome very considerably, approaching the same gains as P1029 types would have. Note that the empirical performance difference will likely be nil, but the codegen does look much more elegant.

  2. If for basic_result<T, E> both T and E are trivially copyable, union-based rather than struct-based storage will be used. This significantly improves performance in synthetic benchmarks which do nothing in deep call stacks of function calls except create and return result<T, E>, and makes Outcome return competitive results to alternative error handling choices, improving comparative optics. It is not expected that the performance difference will be detectable empirically in real world code. It is expected that the build time impact of union storage won’t be noticeable, as union storage for trivially copyable types is much easier than for non-TC types.

  3. The compile time requirement for E types to have a default constructor is removed.

  4. BOOST_OUTCOME_TRY(var, expr) no longer always declares var as auto &&var, but simply uses it as is. This allows TRY to initialise or assign. You can use the macro OUTCOME21_TRY if you want the pre-Outcome v2.2 behaviour. You may find the regular expression _TRY\(([^(]*?),(.*?)\); => _TRY(auto &&\1,\2); of use to you when upgrading code.

Sample usage

The main workhorse in the Outcome library is result<T>: it represents either a successfully computed value of type T, or a std::error_code/boost::system::error_code2 representing the reason for failure. You use it in the function’s return type:

outcome::result<string> data_from_file(string_view path) noexcept;
View this code on Github

It is possible to inspect the state manually:

if (outcome::result<string> rslt = data_from_file("config.cfg"))
  use_string(rslt.value());                   // returns string
  throw LibError{rslt.error(), "config.cfg"}; // returns error_code
View this code on Github

Or, if this function is called in another function that also returns result<T>, you can use a dedicated control statement:

outcome::result<int> process(const string& content) noexcept;

outcome::result<int> int_from_file(string_view path) noexcept
  BOOST_OUTCOME_TRY(str, data_from_file(path));
  // if control gets here data_from_file() has succeeded
  return process(str);  // decltype(str) == string
View this code on Github

BOOST_OUTCOME_TRY is a control statement. If the returned result<T> object contains an error information, the enclosing function is immediately returned with result<U> containing the same failure information; otherwise an automatic object of type T is available in scope.


This library joined the Boost C++ libraries in the 1.70 release (Spring 2019). It can be grafted into much older Boost releases if desired.

  1. If you choose a C-compatible T and E type. [return]
  2. result<T> defaults to std::error_code for Standalone Outcome, and to boost::system::error_code for Boost.Outcome. You can mandate a choice using std_result<T> or boost_result<T>. [return]

Last revised: July 03, 2020 at 14:21:54 +0100

Prev HomeNext