template<typename T>
class pw::Result< T >
Error propagation primitive: value-or error
The pw::Result<T>
class template is a union of a pw::Status
object and an object of type T
. Result<t>
models an object that is either a usable object, or an error (of type pw::Status
) explaining why such an object is not present. It is typically the return value of a function which may fail.
Checking for success
Result<T>
can never hold an OK status; instead, the presence of an object of type T
indicates success. Instead of checking for a kOk
value, use the Result<T>::ok()
member function. (It is for this reason, and code readability, that using the ok()
function is preferred for pw::Status
as well.)
Example:
result->DoSomethingCool();
} else {
PW_LOG_ERROR(
"Calculation failed: %s", result.
status().
str());
}
constexpr bool ok() const
Definition: result.h:447
constexpr Status status() const
Definition: result.h:803
const char * str() const
Definition: status.h:433
Accessing objects
Accessing the object held by a Result<T>
should be performed via operator*
or operator->
, after a call to ok()
confirms that the Result<T>
holds an object of type T
:
Example:
Using Result<T>::value()
when no valid value is present will trigger a PW_ASSERT
.
Example:
const Foo& foo = result.
value();
foo.DoSomethingCool();
constexpr const T & value() const &PW_ATTRIBUTE_LIFETIME_BOUND
Definition: result.h:808
Constructing result objects
A Result<T*>
can be constructed from a null pointer like any other pointer value, and the result will be that ok()
returns true
and value()
returns nullptr
. Checking the value of pointer in a Result<T>
generally requires a bit more care, to ensure both that a value is present and that value is not null:
PW_LOG_ERROR(
"Unable to look up the Foo: %s", result.
status().
str());
} else if (*result == nullptr) {
PW_LOG_ERROR("Unexpected null pointer");
} else {
(*result)->DoSomethingCool();
}
Example factory implementation returning Result<T>
:
if (arg <= 0) {
}
return Foo(arg);
}
static constexpr Status InvalidArgument()
Definition: status.h:164
|
constexpr | Result () |
|
constexpr | Result (const Result &)=default |
| Result<T> is copy constructible if T is copy constructible.
|
|
constexpr Result & | operator= (const Result &)=default |
|
constexpr | Result (Result &&)=default |
| Result<T> is move constructible if T is move constructible.
|
|
constexpr Result & | operator= (Result &&)=default |
|
template<typename U , std::enable_if_t< std::conjunction< std::negation< std::is_same< T, U > >, std::is_constructible< T, const U & >, std::is_convertible< const U &, T >, std::negation< internal_result::IsConstructibleOrConvertibleFromResult< T, U > > >::value, int > = 0> |
constexpr | Result (const Result< U > &other) |
|
template<typename U , std::enable_if_t< std::conjunction< std::negation< std::is_same< T, U > >, std::is_constructible< T, const U & >, std::negation< std::is_convertible< const U &, T > >, std::negation< internal_result::IsConstructibleOrConvertibleFromResult< T, U > > >::value, int > = 0> |
constexpr | Result (const Result< U > &other) |
|
template<typename U , std::enable_if_t< std::conjunction< std::negation< std::is_same< T, U > >, std::is_constructible< T, U && >, std::is_convertible< U &&, T >, std::negation< internal_result::IsConstructibleOrConvertibleFromResult< T, U > > >::value, int > = 0> |
constexpr | Result (Result< U > &&other) |
|
template<typename U , std::enable_if_t< std::conjunction< std::negation< std::is_same< T, U > >, std::is_constructible< T, U && >, std::negation< std::is_convertible< U &&, T > >, std::negation< internal_result::IsConstructibleOrConvertibleFromResult< T, U > > >::value, int > = 0> |
constexpr | Result (Result< U > &&other) |
|
template<typename U , std::enable_if_t< std::conjunction< std::negation< std::is_same< T, U > >, std::is_constructible< T, const U & >, std::is_assignable< T, const U & >, std::negation< internal_result::IsConstructibleOrConvertibleOrAssignableFromResult< T, U > > >::value, int > = 0> |
constexpr Result & | operator= (const Result< U > &other) |
|
template<typename U , std::enable_if_t< std::conjunction< std::negation< std::is_same< T, U > >, std::is_constructible< T, U && >, std::is_assignable< T, U && >, std::negation< internal_result::IsConstructibleOrConvertibleOrAssignableFromResult< T, U > > >::value, int > = 0> |
constexpr Result & | operator= (Result< U > &&other) |
|
template<typename U = Status, std::enable_if_t< std::conjunction< std::is_convertible< U &&, Status >, std::is_constructible< Status, U && >, std::negation< std::is_same< std::decay_t< U >, Result< T > > >, std::negation< std::is_same< std::decay_t< U >, T > >, std::negation< std::is_same< std::decay_t< U >, std::in_place_t > >, std::negation< internal_result::HasConversionOperatorToResult< T, U && > > >::value, int > = 0> |
constexpr | Result (U &&v) |
|
template<typename U = Status, std::enable_if_t< std::conjunction< std::negation< std::is_convertible< U &&, Status > >, std::is_constructible< Status, U && >, std::negation< std::is_same< std::decay_t< U >, Result< T > > >, std::negation< std::is_same< std::decay_t< U >, T > >, std::negation< std::is_same< std::decay_t< U >, std::in_place_t > >, std::negation< internal_result::HasConversionOperatorToResult< T, U && > > >::value, int > = 0> |
constexpr | Result (U &&v) |
|
template<typename U = Status, std::enable_if_t< std::conjunction< std::is_convertible< U &&, Status >, std::is_constructible< Status, U && >, std::negation< std::is_same< std::decay_t< U >, Result< T > > >, std::negation< std::is_same< std::decay_t< U >, T > >, std::negation< std::is_same< std::decay_t< U >, std::in_place_t > >, std::negation< internal_result::HasConversionOperatorToResult< T, U && > > >::value, int > = 0> |
constexpr Result & | operator= (U &&v) |
|
template<typename U = T, typename = typename std::enable_if<std::conjunction< std::is_constructible<T, U&&>, std::is_assignable<T&, U&&>, std::disjunction< std::is_same<std::remove_cv_t<std::remove_reference_t<U>>, T>, std::conjunction< std::negation<std::is_convertible<U&&, Status>>, std::negation< internal_result::HasConversionOperatorToResult<T, U&&>>>>, internal_result::IsForwardingAssignmentValid<T, U&&>>::value>::type> |
constexpr Result & | operator= (U &&v) |
|
template<typename... Args> |
constexpr | Result (std::in_place_t, Args &&... args) |
|
template<typename U , typename... Args> |
constexpr | Result (std::in_place_t, std::initializer_list< U > ilist, Args &&... args) |
|
template<typename U = T, std::enable_if_t< std::conjunction< internal_result::IsDirectInitializationValid< T, U && >, std::is_constructible< T, U && >, std::is_convertible< U &&, T >, std::disjunction< std::is_same< std::remove_cv_t< std::remove_reference_t< U > >, T >, std::conjunction< std::negation< std::is_convertible< U &&, Status > >, std::negation< internal_result::HasConversionOperatorToResult< T, U && > > > > >::value, int > = 0> |
constexpr | Result (U &&u) |
|
template<typename U = T, std::enable_if_t< std::conjunction< internal_result::IsDirectInitializationValid< T, U && >, std::disjunction< std::is_same< std::remove_cv_t< std::remove_reference_t< U > >, T >, std::conjunction< std::negation< std::is_constructible< Status, U && > >, std::negation< internal_result::HasConversionOperatorToResult< T, U && > > > >, std::is_constructible< T, U && >, std::negation< std::is_convertible< U &&, T > > >::value, int > = 0> |
constexpr | Result (U &&u) |
|
constexpr bool | ok () const |
|
constexpr Status | status () const |
|
constexpr const T & | value () const &PW_ATTRIBUTE_LIFETIME_BOUND |
|
constexpr T & | value () &PW_ATTRIBUTE_LIFETIME_BOUND |
|
constexpr const T && | value () const &&PW_ATTRIBUTE_LIFETIME_BOUND |
|
constexpr T && | value () &&PW_ATTRIBUTE_LIFETIME_BOUND |
|
constexpr const T & | operator* () const &PW_ATTRIBUTE_LIFETIME_BOUND |
|
constexpr T & | operator* () &PW_ATTRIBUTE_LIFETIME_BOUND |
|
constexpr const T && | operator* () const &&PW_ATTRIBUTE_LIFETIME_BOUND |
|
constexpr T && | operator* () &&PW_ATTRIBUTE_LIFETIME_BOUND |
|
constexpr const T * | operator-> () const PW_ATTRIBUTE_LIFETIME_BOUND |
|
constexpr T * | operator-> () PW_ATTRIBUTE_LIFETIME_BOUND |
|
template<typename U > |
constexpr T | value_or (U &&default_value) const & |
|
template<typename U > |
constexpr T | value_or (U &&default_value) && |
|
constexpr void | IgnoreError () const |
|
template<typename... Args> |
T & | emplace (Args &&... args) |
|
template<typename U , typename... Args, std::enable_if_t< std::is_constructible< T, std::initializer_list< U > &, Args &&... >::value, int > = 0> |
T & | emplace (std::initializer_list< U > ilist, Args &&... args) |
|
template<typename Fn , typename Ret = internal_result::InvokeResultType<Fn, T&>, std::enable_if_t< std::is_copy_constructible_v< Ret >, int > = 0> |
constexpr Ret | and_then (Fn &&function) & |
|
template<typename Fn , typename Ret = internal_result::InvokeResultType<Fn, T&&>, std::enable_if_t< std::is_move_constructible_v< Ret >, int > = 0> |
constexpr auto | and_then (Fn &&function) && |
|
template<typename Fn , typename Ret = internal_result::InvokeResultType<Fn, const T&>, std::enable_if_t< std::is_copy_constructible_v< Ret >, int > = 0> |
constexpr auto | and_then (Fn &&function) const & |
|
template<typename Fn , typename Ret = internal_result::InvokeResultType<Fn, const T&&>, std::enable_if_t< std::is_move_constructible_v< Ret >, int > = 0> |
constexpr auto | and_then (Fn &&function) const && |
|
template<typename Fn , typename Ret = internal_result::InvokeResultType<Fn, const Status&>, std::enable_if_t<!std::is_void_v< Ret >, int > = 0> |
constexpr Result< T > | or_else (Fn &&function) const & |
|
template<typename Fn , typename Ret = internal_result::InvokeResultType<Fn, const Status&>, std::enable_if_t< std::is_void_v< Ret >, int > = 0> |
constexpr Result< T > | or_else (Fn &&function) const & |
|
template<typename Fn , typename Ret = internal_result::InvokeResultType<Fn, Status&&>, std::enable_if_t<!std::is_void_v< Ret >, int > = 0> |
constexpr Result< T > | or_else (Fn &&function) && |
|
template<typename Fn , typename Ret = internal_result::InvokeResultType<Fn, Status&&>, std::enable_if_t< std::is_void_v< Ret >, int > = 0> |
constexpr Result< T > | or_else (Fn &&function) && |
|
template<typename Fn , typename Ret = internal_result::InvokeResultType<Fn, T&>, std::enable_if_t< std::is_copy_constructible_v< Ret >, int > = 0> |
constexpr Result< Ret > | transform (Fn &&function) & |
|
template<typename Fn , typename Ret = internal_result::InvokeResultType<Fn, T&&>, std::enable_if_t< std::is_move_constructible_v< Ret >, int > = 0> |
constexpr Result< Ret > | transform (Fn &&function) && |
|
template<typename Fn , typename Ret = internal_result::InvokeResultType<Fn, T&>, std::enable_if_t< std::is_copy_constructible_v< Ret >, int > = 0> |
constexpr Result< Ret > | transform (Fn &&function) const & |
|
template<typename Fn , typename Ret = internal_result::InvokeResultType<Fn, T&&>, std::enable_if_t< std::is_move_constructible_v< Ret >, int > = 0> |
constexpr Result< Ret > | transform (Fn &&function) const && |
|
template<typename U > |
constexpr T | value_or (U &&default_value) const & |
|
template<typename U > |
constexpr T | value_or (U &&default_value) && |
|