boost.outcome  0.99
boost.outcome Documentation

Table of Contents

Source
Tarball
Boost.Outcome
on GitHub
CTest summary
dashboard
Linux and MacOS CI:
Windows CI:

Description

This is the Outcome library. It is a C++ 14 library intended to aid ultra-lightweight error handling in large C++ codebases, providing a more expressive and type safe alternative to integer error codes or enums.

Unlike alternative implementations, it works perfectly with exceptions and RTTI disabled and is thus suitable for low-latency/games/finance/SG14 users. One could view Outcome as a minimum overhead universal outcome transport mechanism for C++, hence being named "Outcome".

The Outcome library provides an implementation of expected<T, E> (which is on the C++ 20 standardisation track), with the expected<T, E> refinements outcome<T> and result<T>.

If you are familiar with Swift's error code throws or Rust's Result<T, E>, you will find almost identical semantics in the transports provided here. Outcome even has a BOOST_OUTCOME_TRY macro doing most of the try keyword in Rust and Swift!

Note
Outcome has not been peer reviewed and is not part of the Boost libraries (yet). It will undergo its first round of peer review end of May 2017.

One motivation for this library is to manage errors reported by different means using a single minimum overhead framework. This motivating example should clarify:

// Imagine the libraries you depend on each use different mechanisms for returning errors
namespace outcome = BOOST_OUTCOME_V1_NAMESPACE;
namespace Library1
{ // Like the Filesystem and Networking TS,
auto fun(std::error_code &) noexcept // returns errors via lvalue ref to an error_code.
-> int; // Never throws exceptions.
}
namespace Library2
{ // Throws some exception on error
auto fun()
-> int;
}
namespace Library3 // The Expected proposed for standardisation in C++ 20
{ // Returns an int (expected) or some custom
auto fun() noexcept // error code (unexpected). Never throws exceptions.
-> outcome::expected<int, error_code>;
}
namespace Library4 // Result is an int (not error)
{ // or an outcome::error_code_extended (error)
auto fun() noexcept // Never throws exceptions.
-> outcome::result<int>;
}
// signalling uniform error Outcome is an int, or an outcome::error_code_extended,
// or a std::exception_ptr
auto my_fun() noexcept
-> outcome::outcome<int>
{ // all noexcept functions which could call
try { // throwing code should always have their
std::error_code ec; // bodies wrapped in a try...catch
int i = Library1::fun(ec);
if (ec)
return outcome::make_errored_outcome(ec); // error code returned inside outcome
try {
i += Library2::fun();
}
catch (...) {
return outcome::make_exceptional_outcome<>(); // exception_ptr returned inside outcome
}
if (auto rslt1 = Library3::fun())
i += *rslt1;
else
return outcome::make_errored_outcome(rslt1.error()); // error code returned inside outcome
BOOST_OUTCOME_TRY(rslt2, Library4::fun()); // this may return an outcome with an
// error code, iff fun() reports failure
return i + rslt2; // return outcome with a value
}
catch (...) {
return outcome::make_exceptional_outcome<>(); // construct from std::current_exception()
}
};
// using functions' outcome:
int test()
{
try {
int i = my_fun().value(); // throws if not valued
return i;
}
catch (std::exception const& e) { // e can be used to retrieve
return inspect_exception_to_your_liking(e); // initial error condition
}
}