2.6.0
Freundlich's C++ toolkit
Classes | Typedefs | Functions
fcppt.either

Description

An optional with an error type.

Motivation

Either is a sum of a failure and a success type. As an example, consider reading a series of values from a stream. The following code tries to read an int followed by a string. If either of them fails, an exception is thrown.

typedef
std::pair<
int,
>
int_string_pair;
int_string_pair
read_stream_raw(
std::istream &_stream
)
{
int result_int;
if(
!(_stream >> result_int)
)
throw
std::runtime_error{
"Failed reading the int"
};
std::string result_string;
if(
!(_stream >> result_string)
)
throw
std::runtime_error{
"Failed reading the string"
};
return
int_string_pair{
result_int,
result_string
};
}

Instead of throwing an exception, we can store the exception in an either.

template<
typename Type
>
std::runtime_error,
Type
>
std::istream &_stream,
std::string const &_error
)
{
Type result;
typedef
std::runtime_error,
Type
>
result_type;
return
_stream >> result
?
result_type{
result
}
:
result_type{
std::runtime_error{
_error
}
}
;
}

This can then be used to chain both reading operations together. fcppt::either::apply takes several eithers and combines them iff all contain successes. Otherwise it returns the first error.

std::runtime_error,
int_string_pair
>
read_stream_either(
std::istream &_stream
)
{
std::runtime_error,
int
> const either_int(
int
>(
_stream,
"read int"
)
);
std::runtime_error,
> const either_string(
>(
_stream,
"read string"
)
);
return
[](
int const _i,
std::string const &_s
)
{
return
int_string_pair(
_i,
_s
);
},
either_int,
either_string
);
}

Both fcpptoptional and fcpptvariant are closely related to either. An optional can be thought of as an either with an empty failure type, while a variant generalizes sum types but assigns their components no special meaning.

Operations

As seen in the introduction, multiple eithers can be combined together using fcppt::either::apply. The more basic function fcppt::either::map operates on a single either.

Notice that the example given in the introduction makes use of the fact that an istream can enter the fail state in which all future operations will fail as well. Therefore, it is possible to read multiple eithers from a stream and then combine them together. Imagine this was not possible and it would be an error to continue reading from a failed stream. We would need an operation that not only chains eithers together but also dictates how they are procuded. This is done by fcppt::either::bind:

std::runtime_error,
int_string_pair
>
read_stream_either_bind(
std::istream &_stream
)
{
return
int
>(
_stream,
"read int"
),
[
&_stream
](
int const _int_value
)
{
return
>(
_stream,
"read string"
),
[
_int_value
](
std::string const &_string_value
)
{
return
std::make_pair(
_int_value,
_string_value
);
}
);
}
);
}

The most basic function that acts on the two cases of an either is fcppt::either::match. Again, consider the function from the introduction.

void
either_match(
std::istream &_stream
)
{
read_stream_either(
_stream
),
[](
std::runtime_error const &_error
)
{
<< "Reading failed "
<< _error.what()
<< '\n';
},
[](
int_string_pair const &_result
)
{
<< "The result is "
<< _result.first
<< ", "
<< _result.second
<< '\n';
}
);
}

Alternatively, there is the convenience function fcppt::either::to_exception that throws an exception in case of an error:

void
either_to_exception(
std::istream &_stream
)
{
int_string_pair const result(
read_stream_either(
_stream
),
[](
std::runtime_error const &_error
)
{
return
_error;
}
)
);
<< "The result is "
<< result.first
<< ", "
<< result.second
<< '\n';
}

Errors

When functions return optional errors but no success values, it is more convenient to handle such cases as eithers. An fcppt::either::error is an either with a success type that only has one value, which is fcppt::unit. For example:

auto
either_error(
error_code
> const _error
)
{
error_code
> const either_error{
_error
)
};
return
either_error,
[](
)
{
// Do something in case of no error.
return
do_something();
}
);
}

Header files

Header file Description
object_fwd.hpp Contains either's declaration.
object_decl.hpp Contains either's definition.
object_impl.hpp Contains the definition of either's member functions.
object.hpp Includes object_impl.hpp and comparison.hpp.
apply.hpp Contains fcppt::either::apply.
bind.hpp Contains fcppt::either::bind.
comparison.hpp Contains operator== and operator!=.
error_fwd.hpp Contains error's declaration.
error.hpp Contains error's definition.
error_from_optional.hpp Contains fcppt::either::error_from_optional.
failure_opt.hpp Contains fcppt::either::failure_opt.
first_success.hpp Contains fcppt::either::first_success.
fold_error.hpp Contains fcppt::either::fold_error.
from_optional.hpp Contains fcppt::either::from_optional.
make_failure.hpp Contains fcppt::either::make_failure.
make_success.hpp Contains fcppt::either::make_success.
map.hpp Contains fcppt::either::map.
map_failure.hpp Contains fcppt::either::map_failure.
match.hpp Contains fcppt::either::match.
no_error_fwd.hpp Contains no_error's declaration.
no_error.hpp Contains no_error's definition.
output.hpp Contains operator<<.
sequence.hpp Contains fcppt::either::sequence.
success_opt.hpp Contains fcppt::either::success_opt.
to_exception.hpp Contains fcppt::either::to_exception.
try_call.hpp Contains fcppt::either::try_call.

Classes

class  fcppt::either::object< Failure, Success >
 

Typedefs

template<typename Failure >
using fcppt::either::error = fcppt::either::object< Failure, fcppt::either::no_error >
 An either without a success value. More...
 
typedef fcppt::unit fcppt::either::no_error
 The type that represents no error in an fcppt::either::error. More...
 

Functions

template<typename Function , typename Either1 , typename... Eithers>
auto fcppt::either::apply (Function const &_function, Either1 &&_either1, Eithers &&..._eithers) -> fcppt::either::object< typename std::decay< Either1 >::type::failure, decltype(_function(fcppt::move_if_rvalue< Either1 >(_either1.get_success_unsafe()), fcppt::move_if_rvalue< Eithers >(_eithers.get_success_unsafe())...)) >
 Applies a function to several eithers. More...
 
template<typename Either , typename Function >
auto fcppt::either::bind (Either &&_either, Function const &_function) -> decltype(_function(fcppt::move_if_rvalue< Either >(_either.get_success_unsafe())))
 Monadic bind on the success type of an either. More...
 
template<typename Failure , typename Success >
bool fcppt::either::operator== (fcppt::either::object< Failure, Success > const &_a, fcppt::either::object< Failure, Success > const &_b)
 Compares two eithers for equality. More...
 
template<typename Failure , typename Success >
bool fcppt::either::operator!= (fcppt::either::object< Failure, Success > const &_a, fcppt::either::object< Failure, Success > const &_b)
 Compares two eithers for inequality. More...
 
template<typename Optional >
auto fcppt::either::error_from_optional (Optional &&_optional) -> fcppt::either::error< typename std::decay< Optional >::type::value_type >
 Converts an optional error to an either. More...
 
template<typename Either >
fcppt::optional::object< typename std::decay< Either >::type::failure > fcppt::either::failure_opt (Either &&_either)
 Returns the failure type as an optional. More...
 
template<typename Functions >
fcppt::either::object< std::vector< typename std::result_of< typename Functions::value_type() >::type::failure >, typename std::result_of< typename Functions::value_type() >::type::success > fcppt::either::first_success (Functions const &_functions)
 Call a container of functions, returning their first success or a container of failures. More...
 
template<typename Sequence , typename Function >
auto fcppt::either::fold_error (Sequence &&_sequence, Function const &_function) -> decltype(_function(std::declval< fcppt::container::to_value_type< typename std::remove_reference< Sequence >::type > >()))
 Folds over a range, breaking out on the first error. More...
 
template<typename Optional , typename FailureFunction >
auto fcppt::either::from_optional (Optional &&_optional, FailureFunction const &_failure_function) -> fcppt::either::object< decltype(_failure_function()), typename std::decay< Optional >::type::value_type >
 Converts an optional to an either. More...
 
template<typename Success , typename Failure >
fcppt::either::object< typename std::decay< Failure >::type, Success > fcppt::either::make_failure (Failure &&_failure)
 Create an either with a failure. More...
 
template<typename Failure , typename Success >
fcppt::either::object< Failure, typename std::decay< Success >::type > fcppt::either::make_success (Success &&_success)
 Create an either with a success. More...
 
template<typename Either , typename Function >
auto fcppt::either::map (Either &&_either, Function const &_function) -> fcppt::either::object< typename std::decay< Either >::type::failure, decltype(_function(fcppt::move_if_rvalue< Either >(_either.get_success_unsafe()))) >
 Maps over the success type of an either. More...
 
template<typename Either , typename Function >
auto fcppt::either::map_failure (Either &&_either, Function const &_function) -> fcppt::either::object< decltype(_function(fcppt::move_if_rvalue< Either >(_either.get_failure_unsafe()))), typename std::decay< Either >::type::success >
 Maps over the failure type of an either. More...
 
template<typename Either , typename FailureFunction , typename SuccessFunction >
auto fcppt::either::match (Either &&_either, FailureFunction const &_failure_function, SuccessFunction const &_success_function) -> decltype(_success_function(fcppt::move_if_rvalue< Either >(_either.get_success_unsafe())))
 Matches on the two cases of an either. More...
 
template<typename ResultContainer , typename Source >
fcppt::either::object< typename std::decay< Source >::type::value_type::failure, ResultContainer > fcppt::either::sequence (Source &&_source)
 Sequences a container of eithers. More...
 
template<typename Either >
fcppt::optional::object< typename std::decay< Either >::type::success > fcppt::either::success_opt (Either &&_either)
 Returns the success type as an optional. More...
 
template<typename Either , typename MakeException >
auto fcppt::either::to_exception (Either &&_either, MakeException const _make_exception) -> decltype(fcppt::move_if_rvalue< Either >(_either.get_success_unsafe()))
 Returns the success value contained in an either or throws an exception. More...
 
template<typename Exception , typename Function , typename ToException >
auto fcppt::either::try_call (Function const &_function, ToException const &_to_exception) -> fcppt::either::object< decltype(_to_exception(std::declval< Exception >())), decltype(_function()) >
 Catches exceptions of a function call and puts the result in an either. More...
 

Typedef Documentation

◆ error

template<typename Failure >
using fcppt::either::error = typedef fcppt::either::object< Failure, fcppt::either::no_error >

An either without a success value.

An either with a failure but no success value. This is useful in case errors are returned as optionals.

◆ no_error

The type that represents no error in an fcppt::either::error.

Function Documentation

◆ apply()

template<typename Function , typename Either1 , typename... Eithers>
auto fcppt::either::apply ( Function const &  _function,
Either1 &&  _either1,
Eithers &&...  _eithers 
) -> fcppt::either::object< typename std::decay< Either1 >::type::failure, decltype( _function( fcppt::move_if_rvalue< Either1 >( _either1.get_success_unsafe() ), fcppt::move_if_rvalue< Eithers >( _eithers.get_success_unsafe() )... ) ) >

Applies a function to several eithers.

For eithers e_1 = _either1 and e_2, ..., e_n = _eithers, let i be the smallest number such that e_i is set to failure f. If such an i exists, f is returned. Otherwise, e_1, ...., e_n are set to successes s_1,...,s_n and the result is _function(s_1,...,s_n).

◆ bind()

template<typename Either , typename Function >
auto fcppt::either::bind ( Either &&  _either,
Function const &  _function 
) -> decltype( _function( fcppt::move_if_rvalue< Either >( _either.get_success_unsafe() ) ) )

Monadic bind on the success type of an either.

If _either is set to success s, then _function(s) is returned. Otherwise, the failure in _either is returned.

Template Parameters
FunctionA function callable as either<Either::failure,R> (Either::success) where R is the result type

◆ error_from_optional()

template<typename Optional >
auto fcppt::either::error_from_optional ( Optional &&  _optional) -> fcppt::either::error< typename std::decay< Optional >::type::value_type >

Converts an optional error to an either.

If _optional is set to x, then x is returned as the failure value.

◆ failure_opt()

template<typename Either >
fcppt::optional::object< typename std::decay< Either >::type::failure> fcppt::either::failure_opt ( Either &&  _either)

Returns the failure type as an optional.

◆ first_success()

template<typename Functions >
fcppt::either::object< std::vector< typename std::result_of< typename Functions::value_type() >::type::failure >, typename std::result_of< typename Functions::value_type() >::type::success> fcppt::either::first_success ( Functions const &  _functions)

Call a container of functions, returning their first success or a container of failures.

For _functions = (f_1,...,f_n), let i be the smallest index such that f_i() returns success s, in which case the result is s. If there is no such index, then all functions return failures e_1,...,e_n and the result is (e_1,...,_e_n).

Template Parameters
FunctionsA container of functions callable as fcppt::either::object<F,S> ()

◆ fold_error()

template<typename Sequence , typename Function >
auto fcppt::either::fold_error ( Sequence &&  _sequence,
Function const &  _function 
) -> decltype( _function( std::declval< fcppt::container::to_value_type< typename std::remove_reference< Sequence >::type > >() ) )

Folds over a range, breaking out on the first error.

This function is similar to fcppt::either::sequence, except it does not produce an output sequence. Instead, _function returns fcppt::either::error, which on success contains an fcppt::unit on success. Let _sequence = [x_1, ..., x_n]. The algorithms calls _function(x_1), ..., _function(x_i), where _function(x_i) is either the first call that returns a failure, in which case the failure is returned as the result, or i=n, in which case success is returned.

Template Parameters
SequenceMust be a range.
FunctionMust be a function callable as fcppt::either::error<T>(Sequence::value_type) for some type T.

◆ from_optional()

template<typename Optional , typename FailureFunction >
auto fcppt::either::from_optional ( Optional &&  _optional,
FailureFunction const &  _failure_function 
) -> fcppt::either::object< decltype( _failure_function() ), typename std::decay< Optional >::type::value_type >

Converts an optional to an either.

If _optional is set to x, then x is returned as the success value, otherwise _failure_function() is returned as the failure value.

Template Parameters
FailureFunctionMust be a function callable as R () where R is the failure type

◆ make_failure()

template<typename Success , typename Failure >
fcppt::either::object< typename std::decay< Failure >::type, Success> fcppt::either::make_failure ( Failure &&  _failure)
inline

Create an either with a failure.

Template Parameters
SuccessThe success type of the either.

◆ make_success()

template<typename Failure , typename Success >
fcppt::either::object< Failure, typename std::decay< Success >::type> fcppt::either::make_success ( Success &&  _success)
inline

Create an either with a success.

Template Parameters
FailureThe failure type of the either.

◆ map()

template<typename Either , typename Function >
auto fcppt::either::map ( Either &&  _either,
Function const &  _function 
) -> fcppt::either::object< typename std::decay< Either >::type::failure, decltype( _function( fcppt::move_if_rvalue< Either >( _either.get_success_unsafe() ) ) ) >

Maps over the success type of an either.

If _either is set to success s, r = _function(s) is called and the result is either<Either::failure,decltype(r)>(r). Otherwise, the failure in _either is returned.

Template Parameters
FunctionA function callable as R (Either::success) where R is the result type

◆ map_failure()

template<typename Either , typename Function >
auto fcppt::either::map_failure ( Either &&  _either,
Function const &  _function 
) -> fcppt::either::object< decltype( _function( fcppt::move_if_rvalue< Either >( _either.get_failure_unsafe() ) ) ), typename std::decay< Either >::type::success >

Maps over the failure type of an either.

If _either is set to failure f, r = _function(f) is called and the result is either<decltype(r),Either::success>(r). Otherwise, the success in _either is returned.

Template Parameters
FunctionA function callable as R (Either::failure) where R is the result type

◆ match()

template<typename Either , typename FailureFunction , typename SuccessFunction >
auto fcppt::either::match ( Either &&  _either,
FailureFunction const &  _failure_function,
SuccessFunction const &  _success_function 
) -> decltype( _success_function( fcppt::move_if_rvalue< Either >( _either.get_success_unsafe() ) ) )

Matches on the two cases of an either.

If _either is set to success s, then _success_function(s) is returned. Otherwise, _either is set to failure f and _failure_function(f) is returned.

Template Parameters
FailureFunctionA function callable as R (Either::failure) where R is the result type
SuccessFunctionA function callable as R (Either::success) where R is the result type

◆ operator!=()

template<typename Failure , typename Success >
bool fcppt::either::operator!= ( fcppt::either::object< Failure, Success > const &  _a,
fcppt::either::object< Failure, Success > const &  _b 
)

Compares two eithers for inequality.

◆ operator==()

template<typename Failure , typename Success >
bool fcppt::either::operator== ( fcppt::either::object< Failure, Success > const &  _a,
fcppt::either::object< Failure, Success > const &  _b 
)

Compares two eithers for equality.

◆ sequence()

template<typename ResultContainer , typename Source >
fcppt::either::object< typename std::decay< Source >::type::value_type::failure, ResultContainer> fcppt::either::sequence ( Source &&  _source)

Sequences a container of eithers.

Let _source be a container [e_1,...e_n] of type fcppt::either::object<F,S>. If there is an i such that e_i has failure f and there is no j < i such that e_j has a failure, then f is returned. Otherwise, all eithers have success values, [s_1,...,s_n], and fcppt::either::object<F,ResultContainer>{s_1,...,s_n} is returned.

Template Parameters
ResultContainerMust be a container of type S
SourceMust be an either type

◆ success_opt()

template<typename Either >
fcppt::optional::object< typename std::decay< Either >::type::success> fcppt::either::success_opt ( Either &&  _either)

Returns the success type as an optional.

◆ to_exception()

template<typename Either , typename MakeException >
auto fcppt::either::to_exception ( Either &&  _either,
MakeException const  _make_exception 
) -> decltype( fcppt::move_if_rvalue< Either >( _either.get_success_unsafe() ) )
inline

Returns the success value contained in an either or throws an exception.

If _either is set to success s, then s is returned. Otherwise, _either is set to failure f and the result of _make_exception(f) is thrown as an exception.

Template Parameters
MakeExceptionMust be a function callable as E (Either::failure) where E is the exception type

◆ try_call()

template<typename Exception , typename Function , typename ToException >
auto fcppt::either::try_call ( Function const &  _function,
ToException const &  _to_exception 
) -> fcppt::either::object< decltype( _to_exception( std::declval< Exception >() ) ), decltype( _function() ) >

Catches exceptions of a function call and puts the result in an either.

Calls _function in a try block. If _function returns s, then the result is success s. If the function throws an exception e of type Exception, then the result is the failure _to_exception(e).

Template Parameters
FunctionA function callable as S () where S is the success result type
ToExceptionA function callable as E (Exception) where E is the failure result type