Result

Result provides a way to return a value or an error. The concept is similar to Either in Haskell or Result in Rust.

Usage

Use value, error, emplace_value and emplace_error to create new Result.

auto value42 = atoms::Result< int >::value( 22 );
auto value0 = atoms::Result< int, std::runtime_error >::emplace_value();
auto errStr = atoms::Result< double >::error( "string is default error type" );
auto errExcept = atoms::Result< int, std::runtime_error >::emplace_error( "passed to constructor" );

When returning Result from a function, you can use helper creation functions.

atoms::Result< int > div( int lhs, int rhs ) {
    if ( rhs == 0 ) {
        return atoms::result_error< std::string >( "division by 0" );
    }
    return atoms::result_value( lhs / rhs );
}

Use make_ helper creation function variants to pass arguments directly to constuctors.

atoms::Result< std::vector< double > > repeat( int count, double value ) {
    if ( count < 0 ) {
        return atoms::make_result_error< std::string >( "count is negative" );
    }
    return atoms::make_result_value( count, value );
}

You can check if a Result contains a value and dereference the Result to get it.

auto result = atoms::Result< int >::value( 10 );

if ( result ) { // or `result.has_value()`
    std::cout << "Have result " << *result << "\n"; // or `result.assume_value()`
} else {
    std::cout << "Have error " << result.assume_error() << "\n";
}

You can use monadic methods based on std::optional. Note that when using monadic methods, the other type has to be copy/move constructible.

auto result = atoms::Result< int >::value( 10 );

auto newResult = result.and_then( []( int value ){
        return atoms::result_error( std::to_string( value ) );
    } )
    .or_else( []( const std::string & str ) {
        return atoms::value( static_cast< int >( str.size() ) );
    } )
    .or_else( []() {
        return atoms::value( 12 );
    } )
    .transform( []( int value ){
        return static_cast< unsigned >( value + 2 );
    } );

// If you `std::move` the result, the content will be moved as well
unsigned newValue = std::move( newResult ).transform_error( []( std::string str ){
        return "Error: " + std::move( str );
    } )
    .value_or( []( std::string error ){
        throw std::runtime_error( std::move( error ) );
    } );

For matching on a result, you can use Result::match methods.

#include <atoms/util.hpp> // for `overloaded`

// ...

auto correctAnswer = atoms::Result< int >::value( 10 );

correctAnswer.match( overloaded{
    []( int value ) { std::cout << "Got answer " << value << "\n"; }
    []( const std::string & error ) { std::cerr << "Got error: " << error << "\n"; }
} );

// With compatible value and error types
auto correctStrAnswer = atoms::Result< std::string, std::string >::value( "Apple" );

/**
 * Doesn't compile (compiler cannot deduce value/error from type)
 * Also doesn't work on compatible types (e.g. int/unsigned) for the programmer's safety.
 */
// correctAnswer.match( overloaded{
//     []( const std::string & value ) { std::cout << "Got answer " << value << "\n"; }
//     []( const std::string & error ) { std::cerr << "Got error: " << error << "\n"; }
// } );

correctAnswer.match( overloaded{
    []( std::true_type, const std::string & value ) { std::cout << "Got answer " << value << "\n"; }
    []( std::false_type, const std::string & error ) { std::cerr << "Got error: " << error << "\n"; }
} );

Classes reference

template<typename T, typename E = std::string>
class atoms::Result

A type that holds either a value or an error.

The usecase is similar to that of std::optional except it can hold additional info about the failure.

The Result class template is designed to be an almost drop-in replacement for std::optional except the construction.

Member types

using value_type = T
using error_type = E

Constructing static member functions

static inline constexpr Result value(const value_type &val)

Constructs the contained value by the copy constructor.

static inline constexpr Result value(value_type &&val)

Constructs the contained value by the move constructor.

static inline constexpr Result emplace_value(auto&&... args)

Constructs the contained value in-place.

static inline constexpr Result error(const error_type &err)

Constructs the contained error by the copy constructor.

static inline constexpr Result error(error_type &&err)

Constructs the contained error by the move constructor.

static inline constexpr Result emplace_error(auto&&... args)

Constructs the contained error in-place.

Implicit conversions

Implicit conversions when one of types is detail::TypePlaceholder

template<typename ValueT>
inline constexpr operator Result<ValueT, error_type>() const &

Changes the value_type from detail::TypePlaceholder by copying.

template<typename ValueT>
inline constexpr operator Result<ValueT, error_type>() &&

Changes the value_type from detail::TypePlaceholder by moving.

template<typename ErrorT>
inline constexpr operator Result<value_type, ErrorT>() const &

Changes the error_type from detail::TypePlaceholder by copying.

template<typename ErrorT>
inline constexpr operator Result<value_type, ErrorT>() &&

Changes the error_type from detail::TypePlaceholder by moving.

Observers

inline constexpr bool has_value() const noexcept

Checks whether *this contains a value.

Return values
  • true – if *this contains a value.

  • false – if *this contains an error.

inline constexpr operator bool() const noexcept

Checks whether *this contains a value.

Return values
  • true – if *this contains a value.

  • false – if *this contains an error.

Accessors

inline constexpr value_type *operator->() noexcept

Accesses the contained value.

Returns

Pointer to the contained value.

inline constexpr const value_type *operator->() const noexcept

Accesses the contained value.

Returns

Pointer to the contained value.

inline constexpr value_type &operator*() & noexcept

Accesses the contained value.

Returns

Reference to the contained value.

inline constexpr const value_type &operator*() const & noexcept

Accesses the contained value.

Returns

Reference to the contained value.

inline constexpr value_type &&operator*() && noexcept

Accesses the contained value.

Returns

Reference to the contained value.

inline constexpr value_type &assume_value() & noexcept

Assume that the result contains a value.

Returns

Reference to the contained value.

inline constexpr const value_type &assume_value() const & noexcept

Assume that the result contains a value.

Returns

Reference to the contained value.

inline constexpr value_type &&assume_value() && noexcept

Assume that the result contains a value.

Returns

Reference to the contained value.

inline constexpr error_type &assume_error() & noexcept

Assume that the result contains an error.

Returns

Reference to the contained error.

inline constexpr const error_type &assume_error() const & noexcept

Assume that the result contains an error.

Returns

Reference to the contained error.

inline constexpr error_type &&assume_error() && noexcept

Assume that the result contains an error.

Returns

Reference to the contained error.

Monadic operations

Inspired by and designed to be compatible with monadic operations of std::optional from C++23.

template<std::invocable<value_type&> F>
inline constexpr auto and_then(F &&f) &

Returns the result of invocation of f on the contained value if it exists.

Otherwise, returns the contained error in the return type.

The return type must be a specialization of Result with the same error type.

Parameters

f – a suitable function or Callable object that returns a Result

Returns

The result of f or the contained error.

template<std::invocable<const value_type&> F>
inline constexpr auto and_then(F &&f) const &

Returns the result of invocation of f on the contained value if it exists.

Otherwise, returns the contained error in the return type.

The return type must be a specialization of Result with the same error type.

Parameters

f – a suitable function or Callable object that returns a Result

Returns

The result of f or the contained error.

template<std::invocable<value_type&&> F>
inline constexpr auto and_then(F &&f) &&

Returns the result of invocation of f on the contained value if it exists.

Otherwise, returns the contained error in the return type.

The return type must be a specialization of Result with the same error type.

Parameters

f – a suitable function or Callable object that returns a Result

Returns

The result of f or the contained error.

template<std::invocable<error_type&> F>
inline constexpr auto or_else(F &&f) &

Returns the contained value in the return type if it contains a value.

Otherwise, returns the result of invocation of f on the contained error.

The return type must be a specialization of Result with the same value type.

Parameters

f – a suitable function or Callable object that returns a Result

Returns

The contained value or the result of f .

template<std::invocable<const error_type&> F>
inline constexpr auto or_else(F &&f) const &

Returns the contained value in the return type if it contains a value.

Otherwise, returns the result of invocation of f on the contained error.

The return type must be a specialization of Result with the same value type.

Parameters

f – a suitable function or Callable object that returns a Result

Returns

The contained value or the result of f .

template<std::invocable<error_type&&> F>
inline constexpr auto or_else(F &&f) &&

Returns the contained value in the return type if it contains a value.

Otherwise, returns the result of invocation of f on the contained error.

The return type must be a specialization of Result with the same value type.

Parameters

f – a suitable function or Callable object that returns a Result

Returns

The contained value or the result of f .

template<std::invocable<> F>
inline constexpr auto or_else(F &&f) const

Returns the contained value in the return type if it contains a value.

Otherwise, returns the result of f .

The return type must be a specialization of Result with the same value type.

Parameters

f – a suitable function or Callable object that returns a Result

Returns

The contained value or the result of f .

template<std::invocable<> F>
inline constexpr auto or_else(F &&f) &&

Returns the contained value in the return type if it contains a value.

Otherwise, returns the result of f .

The return type must be a specialization of Result with the same value type.

Parameters

f – a suitable function or Callable object that returns a Result

Returns

The contained value or the result of f .

Transform operations

template<std::invocable<value_type&> F>
inline constexpr auto transform(F &&f) &

Returns Result with the result of invocation of f on the contained value as the new value if it exists.

Otherwise, returns the contained error in the return type.

The return type of f will be the value type of the returned Result.

Parameters

f – a suitable function or Callable object that returns the new value type

Returns

The result of f or the contained error.

template<std::invocable<const value_type&> F>
inline constexpr auto transform(F &&f) const &

Returns Result with the result of invocation of f on the contained value as the new value if it exists.

Otherwise, returns the contained error in the return type.

The return type of f will be the value type of the returned Result.

Parameters

f – a suitable function or Callable object that returns the new value type

Returns

The result of f or the contained error.

template<std::invocable<value_type&&> F>
inline constexpr auto transform(F &&f) &&

Returns Result with the result of invocation of f on the contained value as the new value if it exists.

Otherwise, returns the contained error in the return type.

The return type of f will be the value type of the returned Result.

Parameters

f – a suitable function or Callable object that returns the new value type

Returns

The result of f or the contained error.

template<std::invocable<error_type&> F>
inline constexpr auto transform_error(F &&f) &

Returns the contained value in the return type if it contains a value.

Otherwise, returns Result with the result of invocation of f on the contained error as the new error.

The return type of f will be the error type of the returned Result.

Parameters

f – a suitable function or Callable object that returns a Result

Returns

The contained value or the result of f .

template<std::invocable<const error_type&> F>
inline constexpr auto transform_error(F &&f) const &

Returns the contained value in the return type if it contains a value.

Otherwise, returns Result with the result of invocation of f on the contained error as the new error.

The return type of f will be the error type of the returned Result.

Parameters

f – a suitable function or Callable object that returns a Result

Returns

The contained value or the result of f .

template<std::invocable<error_type&&> F>
inline constexpr auto transform_error(F &&f) &&

Returns the contained value in the return type if it contains a value.

Otherwise, returns Result with the result of invocation of f on the contained error as the new error.

The return type of f will be the error type of the returned Result.

Parameters

f – a suitable function or Callable object that returns a Result

Returns

The contained value or the result of f .

Match operations

template<detail::hint_match_visitor<value_type&, error_type&> Vis>
inline constexpr auto match(Vis &&vis) &

Returns the result of invocation of vis on std::true_type and the contained value if it exists.

Otherwise, returns the result of invocation of vis on std::false_type and the contained error.

vis has to be invocable with std::true_type, value_type & and with std::false_type, error_type & and has to have the same return type.

vis cannot be invocable just with value_type & or just with error_type &.

Parameters

vis – a suitable function or Callable object

Returns

The result of vis .

template<detail::hint_match_visitor<const value_type&, const error_type&> Vis>
inline constexpr auto match(Vis &&vis) const &

Returns the result of invocation of vis on std::true_type and the contained value if it exists.

Otherwise, returns the result of invocation of vis on std::false_type and the contained error.

vis has to be invocable with std::true_type, const value_type & and with std::false_type, const error_type & and has to have the same return type.

vis cannot be invocable just with const value_type & or just with const error_type &.

Parameters

vis – a suitable function or Callable object

Returns

The result of vis .

template<detail::hint_match_visitor<value_type&&, error_type&&> Vis>
inline constexpr auto match(Vis &&vis) &&

Returns the result of invocation of vis on std::true_type and the contained value if it exists.

Otherwise, returns the result of invocation of vis on std::false_type and the contained error.

vis has to be invocable with std::true_type, value_type && and with std::false_type, error_type && and has to have the same return type.

vis cannot be invocable just with value_type && or just with error_type &&.

Parameters

vis – a suitable function or Callable object

Returns

The result of vis .

template<detail::no_hint_match_visitor<value_type&, error_type&> Vis>
inline constexpr auto match(Vis &&vis) &

Returns the result of invocation of vis on the contained value if it exists.

Otherwise, returns the result of invocation of vis on the contained error.

vis has to be invocable with value_type & and with error_type & and has to have the same return type.

vis cannot be invocable with std::true_type, value_type & or with std::false_type, error_type &.

Parameters

vis – a suitable function or Callable object

Returns

The result of vis .

template<detail::no_hint_match_visitor<const value_type&, const error_type&> Vis>
inline constexpr auto match(Vis &&vis) const &

Returns the result of invocation of vis on the contained value if it exists.

Otherwise, returns the result of invocation of vis on the contained error.

vis has to be invocable with const value_type & and with const error_type & and has to have the same return type.

vis cannot be invocable with std::true_type, const value_type & or with std::false_type, const error_type &.

Parameters

vis – a suitable function or Callable object

Returns

The result of vis .

template<detail::no_hint_match_visitor<value_type&&, error_type&&> Vis>
inline constexpr auto match(Vis &&vis) &&

Returns the result of invocation of vis on the contained value if it exists.

Otherwise, returns the result of invocation of vis on the contained error.

vis has to be invocable with value_type && and with error_type && and has to have the same return type.

vis cannot be invocable with std::true_type, value_type && or with std::false_type, error_type &&.

Parameters

vis – a suitable function or Callable object

Returns

The result of vis .

Comparison operator

bool operator==(const Result &other) const = default

Checks equality of two results.

Parameters

other – result to check equality against

Returns

whether both *this and other contain value and the values are equal or both contain error and the errors are equal.

struct atoms::detail::TypePlaceholder

Result value/error type placeholder.

Used as a type placeholder so the other type of result doesn’t have to be specified by the user.

The functionality of Result with TypePlaceholder is similar to std::nullopt_t.

Public Functions

TypePlaceholder() = delete

Functions reference

template<typename ValueT>
inline constexpr auto atoms::result_value(ValueT value) -> Result<ValueT, detail::TypePlaceholder>

Creates Result from value.

The created Result is implicitly convertible to Result with any error type.

Parameters

value – the value to construct the Result object with

Returns

the contructed Result object.

template<typename ValueT, typename ...Args>
inline constexpr auto atoms::make_result_value(Args&&... args) -> Result<ValueT, detail::TypePlaceholder>

Creates Result with value constructed in-place from args… .

The created Result is implicitly convertible to Result with any error type.

Parameters

args – arguments to be passed to the constructor of value

Returns

the contructed Result object.

template<typename ErrorT>
inline constexpr auto atoms::result_error(ErrorT error) -> Result<detail::TypePlaceholder, ErrorT>

Creates Result from error.

The created Result is implicitly convertible to Result with any value type.

Parameters

error – the error to construct the Result object with

Returns

the contructed Result object.

template<typename ErrorT, typename ...Args>
inline constexpr auto atoms::make_result_error(Args&&... args) -> Result<detail::TypePlaceholder, ErrorT>

Creates Result with error constructed in-place from args… .

The created Result is implicitly convertible to Result with any value type.

Parameters

args – arguments to be passed to the constructor of error

Returns

the contructed Result object.