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 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 forstd::optional
except the construction.The
Result
is similar tostd::variant
and should be treated as such. Specifically usestd::monostate
ifT
orE
types don’t have a value.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.
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
fromdetail::TypePlaceholder
by copying.
-
template<typename ValueT>
inline constexpr operator Result<ValueT, error_type>() && Changes the
value_type
fromdetail::TypePlaceholder
by moving.
-
template<typename ErrorT>
inline constexpr operator Result<value_type, ErrorT>() const & Changes the
error_type
fromdetail::TypePlaceholder
by copying.
-
template<typename ErrorT>
inline constexpr operator Result<value_type, ErrorT>() && Changes the
error_type
fromdetail::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.
-
inline constexpr Result<detail::TypePlaceholder, error_type> assume_error_result() & noexcept
Assume that the result contains an error.
Deletes the
value_type
sothis
can be converted to anotherResult
.- Returns
Result
containing error fromthis
.
-
inline constexpr Result<detail::TypePlaceholder, error_type> assume_error_result() const & noexcept
Assume that the result contains an error.
Deletes the
value_type
sothis
can be converted to anotherResult
.- Returns
Result
containing error fromthis
.
-
inline constexpr Result<detail::TypePlaceholder, error_type> assume_error_result() && noexcept
Assume that the result contains an error.
Deletes the
value_type
sothis
can be converted to anotherResult
.- Returns
Result
containing error fromthis
.
Get or throw operations
-
inline constexpr value_type &get_or_throw() &
Returns the contained value if it contains a value.
Otherwise, throws the contained error as an exception.
- Throws
If – the result type contains an error throws exception of type
error_type
.- Returns
The contained value or doesn’t return normally.
-
inline constexpr const value_type &get_or_throw() const &
Returns the contained value if it contains a value.
Otherwise, throws the contained error as an exception.
- Throws
If – the result type contains an error throws exception of type
error_type
.- Returns
The contained value or doesn’t return normally.
-
inline constexpr value_type &&get_or_throw() &&
Returns the contained value if it contains a value.
Otherwise, throws the contained error as an exception.
- Throws
If – the result type contains an error throws exception of type
error_type
.- Returns
The contained value or doesn’t return normally.
-
template<std::constructible_from<error_type&> ExceptionT>
inline constexpr value_type &get_or_throw_as() & Returns the contained value if
this
contains a value.Otherwise, throws the
ExceptionT
constructed from the error.- Template Parameters
ExceptionT – exception type constructable from
value_type &
- Throws
If – the result type contains an error throws exception of type
ExceptionT
.- Returns
The contained value or doesn’t return normally.
-
template<std::constructible_from<const error_type&> ExceptionT>
inline constexpr const value_type &get_or_throw_as() const & Returns the contained value if
this
contains a value.Otherwise, throws the
ExceptionT
constructed from the error.- Template Parameters
ExceptionT – exception type constructable from
value_type &
- Throws
If – the result type contains an error throws exception of type
ExceptionT
.- Returns
The contained value or doesn’t return normally.
-
template<std::constructible_from<error_type&&> ExceptionT>
inline constexpr value_type &&get_or_throw_as() && Returns the contained value if
this
contains a value.Otherwise, throws the
ExceptionT
constructed from the error.- Template Parameters
ExceptionT – exception type constructable from
value_type &
- Throws
If – the result type contains an error throws exception of type
ExceptionT
.- Returns
The contained value or doesn’t return normally.
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 off
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 returnedResult
.- 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 off
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 returnedResult
.- 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 off
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 returnedResult
.- 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 off
on the contained error as the new error.The return type of
f
will be the error type of the returnedResult
.- 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 off
on the contained error as the new error.The return type of
f
will be the error type of the returnedResult
.- 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 off
on the contained error as the new error.The return type of
f
will be the error type of the returnedResult
.- 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
onstd::true_type
and the contained value if it exists.Otherwise, returns the result of invocation of
vis
onstd::false_type
and the contained error.vis
has to be invocable withstd::true_type, value_type &
and withstd::false_type, error_type &
and has to have the same return type.vis
cannot be invocable just withvalue_type &
or just witherror_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
onstd::true_type
and the contained value if it exists.Otherwise, returns the result of invocation of
vis
onstd::false_type
and the contained error.vis
has to be invocable withstd::true_type, const value_type &
and withstd::false_type, const error_type &
and has to have the same return type.vis
cannot be invocable just withconst value_type &
or just withconst 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
onstd::true_type
and the contained value if it exists.Otherwise, returns the result of invocation of
vis
onstd::false_type
and the contained error.vis
has to be invocable withstd::true_type, value_type &&
and withstd::false_type, error_type &&
and has to have the same return type.vis
cannot be invocable just withvalue_type &&
or just witherror_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 withvalue_type &
and witherror_type &
and has to have the same return type.vis
cannot be invocable withstd::true_type, value_type &
or withstd::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 withconst value_type &
and withconst error_type &
and has to have the same return type.vis
cannot be invocable withstd::true_type, const value_type &
or withstd::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 withvalue_type &&
and witherror_type &&
and has to have the same return type.vis
cannot be invocable withstd::true_type, value_type &&
or withstd::false_type, error_type &&
.- Parameters
vis – a suitable function or Callable object
- Returns
The result of
vis
.
-
static inline constexpr Result value(const value_type &val)
-
struct 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
withTypePlaceholder
is similar tostd::nullopt_t
.Public Functions
-
TypePlaceholder() = delete
-
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 toResult
with any error type.
-
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 fromargs
… .The created
Result
is implicitly convertible toResult
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 toResult
with any value type.
-
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 fromargs
… .The created
Result
is implicitly convertible toResult
with any value type.- Parameters
args – arguments to be passed to the constructor of error
- Returns
the contructed
Result
object.