EtcPal  HEAD (unstable)
ETC Platform Abstraction Layer (EtcPal)
View other versions:
Expected< T > Class Template Reference

Overview

template<typename T>
class etcpal::Expected< T >

A type representing either a value or an etcpal_error_t code.

This class is modeled after the std::expected proposal. It is a useful companion to C++17's std::optional, when one desires a concise representation of either a value or an error code representing why that value is not present.

The proposed std::expected is generic with respect to both the value and the error type, but EtcPal's version always uses etcpal_error_t as the error. This makes it useful in the context of EtcPal itself and libraries that depend on EtcPal; if you are looking for a generically-useful expected implementation, martinmoene's version is recommended. This implementation is based heavily on that one.

Usage

Expected is almost always used as the return type of an API function. Consider a function that either creates a network socket or returns an error.

etcpal::Expected<etcpal_socket_t> CreateSocket(int family, int type);
A type representing either a value or an etcpal_error_t code.
Definition: error.h:477

When using this function, check whether the result contains an error:

auto socket_res = CreateSocket(AF_INET, SOCK_STREAM);
if (socket_res) // or socket_res.has_value()
{
etcpal_socket_t socket = *socket_res; // or socket_res.value()
// Now use the socket...
}
else
{
printf("CreateSocket failed with result code %d, description '%s'\n", socket_res.error(),
socket_res.result().ToCString());
}
PLATFORM_DEFINED etcpal_socket_t
A socket handle.
Definition: socket.dox:11

value() throws BadExpectedAccess if the instance does not have a valid value. So you can also use an exception-handling approach:

try
{
etcpal_socket_t socket = CreateSocket(AF_INET, SOCK_STREAM).value();
}
catch (const etcpal::BadExpectedAccess& e)
{
printf("CreateSocket failed with result code %d, description '%s'\n", e.result().code(),
e.result().ToCString());
}
Exception representing bad access to an Expected instance.
Definition: error.h:218

Note that this only works for the value() function, not any of the other accessors (they assert on the correct state instead).

Inside functions that return Expected, you can use implicit conversions from the value type or etcpal_error_t to return success or failure:

// Possible implementation of CreateSocket()...
etcpal::Expected<etcpal_socket_t> CreateSocket(int family, int type)
{
etcpal_error_t res = etcpal_socket(family, type, &socket);
if (res == kEtcPalErrOk)
return socket; // Implicitly converted to Expected, has_value() is true
else
return res; // Implicitly converted to Expected, has_value() is false
}
etcpal_error_t
A set of error codes that can be returned by library functions.
Definition: error.h:49
@ kEtcPalErrOk
The call was successful, no error occurred.
Definition: error.h:51
etcpal_error_t etcpal_socket(unsigned int family, unsigned int type, etcpal_socket_t *id)
Create a socket.

The value_or() function can be useful when you want to use a default value in case of an error condition:

etcpal::Expected<std::string> ConvertIntToString(int val);
// ...
std::string conversion = ConvertIntToString(arg).value_or("0");
// Conversion contains the successful conversion result, or "0" if the conversion failed.

Public Types

using ValueType = T
 The value type.
 

Public Member Functions

template<bool B = std::is_default_constructible<T>::value, typename std::enable_if< B, int >::type = 0>
ETCPAL_CONSTEXPR_14 Expected ()
 Default constructor - enabled if T is default-constructible. More...
 
ETCPAL_CONSTEXPR_14 Expected (const Expected &other)=default
 Copy constructor - enabled if T is copy-constructible. More...
 
ETCPAL_CONSTEXPR_14 Expected (Expected &&other)=default
 Move constructor - enabled if T is move-constructible. More...
 
template<typename U >
ETCPAL_CONSTEXPR_14 Expected (const Expected< U > &other, ETCPAL_ENABLE_IF_ARG(std::is_constructible< T, const U & >::value &&!std::is_constructible< T, Expected< U > & >::value &&!std::is_constructible< T, Expected< U > && >::value &&!std::is_constructible< T, Expected< U > const & >::value &&!std::is_constructible< T, Expected< U > const && >::value &&!std::is_convertible< Expected< U > &, T >::value &&!std::is_convertible< Expected< U > &&, T >::value &&!std::is_convertible< Expected< U > const &, T >::value &&!std::is_convertible< Expected< U > const &&, T >::value &&!std::is_convertible< const U &, T >::value))
 Explicit conversion copy constructor - enabled for U that can be explicitly converted to T. More...
 
template<typename U >
ETCPAL_CONSTEXPR_14 Expected (const Expected< U > &other, ETCPAL_ENABLE_IF_ARG(std::is_constructible< T, const U & >::value &&!std::is_constructible< T, Expected< U > & >::value &&!std::is_constructible< T, Expected< U > && >::value &&!std::is_constructible< T, Expected< U > const & >::value &&!std::is_constructible< T, Expected< U > const && >::value &&!std::is_convertible< Expected< U > &, T >::value &&!std::is_convertible< Expected< U > &&, T >::value &&!std::is_convertible< Expected< U > const &, T >::value &&!std::is_convertible< Expected< U > const &&, T >::value &&std::is_convertible< const U &, T >::value))
 Implicit conversion copy constructor - enabled for U that can be implicitly converted to T. More...
 
template<typename U >
ETCPAL_CONSTEXPR_14 Expected (Expected< U > &&other, ETCPAL_ENABLE_IF_ARG(std::is_constructible< T, U >::value &&!std::is_constructible< T, Expected< U > & >::value &&!std::is_constructible< T, Expected< U > && >::value &&!std::is_constructible< T, Expected< U > const & >::value &&!std::is_constructible< T, Expected< U > const && >::value &&!std::is_convertible< Expected< U > &, T >::value &&!std::is_convertible< Expected< U > &&, T >::value &&!std::is_convertible< Expected< U > const &, T >::value &&!std::is_convertible< Expected< U > const &&, T >::value &&!std::is_convertible< U, T >::value))
 Explicit conversion move constructor - enabled for U that can be explicitly converted to T. More...
 
template<typename U >
ETCPAL_CONSTEXPR_14 Expected (Expected< U > &&other, ETCPAL_ENABLE_IF_ARG(std::is_constructible< T, U >::value &&!std::is_constructible< T, Expected< U > & >::value &&!std::is_constructible< T, Expected< U > && >::value &&!std::is_constructible< T, Expected< U > const & >::value &&!std::is_constructible< T, Expected< U > const && >::value &&!std::is_convertible< Expected< U > &, T >::value &&!std::is_convertible< Expected< U > &&, T >::value &&!std::is_convertible< Expected< U > const &, T >::value &&!std::is_convertible< Expected< U > const &&, T >::value &&std::is_convertible< U, T >::value))
 Implicit conversion move constructor - enabled for U that can be implicitly converted to T. More...
 
template<typename U = T>
ETCPAL_CONSTEXPR_14 Expected (U &&value, ETCPAL_ENABLE_IF_ARG(std::is_constructible< T, U && >::value &&!std::is_convertible< U &&, T >::value)) noexcept(std::is_nothrow_move_constructible< U >::value)
 Construct from value, explicit. More...
 
template<typename U = T>
ETCPAL_CONSTEXPR_14 Expected (U &&value, ETCPAL_ENABLE_IF_ARG(std::is_constructible< T, U && >::value &&std::is_convertible< U &&, T >::value)) noexcept(std::is_nothrow_move_constructible< U >::value)
 Construct from value, implicit. More...
 
ETCPAL_CONSTEXPR_14 Expected (etcpal_error_t error)
 Construct an Expected instance containing an error code.
 
 ~Expected ()
 Calls the contained value's destructor if and only if has_value() is true.
 
constexpr const T * operator-> () const
 Access members of a composite contained value. More...
 
T * operator-> ()
 Access members of a composite contained value. More...
 
constexpr const T & operator* () const &
 Get the underlying value. More...
 
T & operator* () &
 Get the underlying value. More...
 
constexpr const T && operator* () const &&
 Get the underlying value. More...
 
ETCPAL_CONSTEXPR_14 T && operator* () &&
 Get the underlying value. More...
 
constexpr operator bool () const noexcept
 Evaluate the Expected instance inline - evaluates to has_value().
 
constexpr bool has_value () const noexcept
 Whether this Expected instance contains a valid value. If not, contains an error code.
 
ETCPAL_CONSTEXPR_14 const T & value () const &
 Get the underlying value. More...
 
T & value () &
 Get the underlying value. More...
 
ETCPAL_CONSTEXPR_14 const T && value () const &&
 Get the underlying value. More...
 
ETCPAL_CONSTEXPR_14 T && value () &&
 Get the underlying value. More...
 
constexpr etcpal_error_t error_code () const noexcept
 Get the error code. More...
 
constexpr Error error () const noexcept
 Get the error code as a Error object. More...
 
template<typename U , ETCPAL_ENABLE_IF_TEMPLATE(std::is_copy_constructible< T >::value &&std::is_convertible< U &&, T >::value) >
constexpr T value_or (U &&def_val) const &
 Get the value, or a default value if this Expected contains an error. More...
 
template<typename U , ETCPAL_ENABLE_IF_TEMPLATE(std::is_move_constructible< T >::value &&std::is_convertible< U &&, T >::value) >
value_or (U &&def_val) &&
 Get the value, or a default value if this Expected contains an error. More...
 

Constructor & Destructor Documentation

◆ Expected() [1/9]

Default constructor - enabled if T is default-constructible.

Default-constructs an instance of T. This Expected instance has a value after this constructor is called.

◆ Expected() [2/9]

ETCPAL_CONSTEXPR_14 Expected ( const Expected< T > &  other)
default

Copy constructor - enabled if T is copy-constructible.

If other has a value, copies its value into this Expected. If other does not have a value, copies its error code into this Expected.

◆ Expected() [3/9]

ETCPAL_CONSTEXPR_14 Expected ( Expected< T > &&  other)
default

Move constructor - enabled if T is move-constructible.

If other has a value, moves its value into this Expected. If other does not have a value, copies its error code into this Expected.

◆ Expected() [4/9]

ETCPAL_CONSTEXPR_14 Expected ( const Expected< U > &  other,
ETCPAL_ENABLE_IF_ARG( std::is_constructible< T, const U & >::value && !std::is_constructible< T, Expected< U > & >::value && !std::is_constructible< T, Expected< U > && >::value && !std::is_constructible< T, Expected< U > const & >::value && !std::is_constructible< T, Expected< U > const && >::value && !std::is_convertible< Expected< U > &, T >::value && !std::is_convertible< Expected< U > &&, T >::value && !std::is_convertible< Expected< U > const &, T >::value && !std::is_convertible< Expected< U > const &&, T >::value && !std::is_convertible< const U &, T >::value  
)
inlineexplicit

Explicit conversion copy constructor - enabled for U that can be explicitly converted to T.

If other has a value, copies its value into this Expected. If other does not have a value, copies its error code into this Expected.

◆ Expected() [5/9]

ETCPAL_CONSTEXPR_14 Expected ( const Expected< U > &  other,
ETCPAL_ENABLE_IF_ARG( std::is_constructible< T, const U & >::value && !std::is_constructible< T, Expected< U > & >::value && !std::is_constructible< T, Expected< U > && >::value && !std::is_constructible< T, Expected< U > const & >::value && !std::is_constructible< T, Expected< U > const && >::value && !std::is_convertible< Expected< U > &, T >::value && !std::is_convertible< Expected< U > &&, T >::value && !std::is_convertible< Expected< U > const &, T >::value && !std::is_convertible< Expected< U > const &&, T >::value && std::is_convertible< const U &, T >::value  
)
inline

Implicit conversion copy constructor - enabled for U that can be implicitly converted to T.

If other has a value, copies its value into this Expected. If other does not have a value, copies its error code into this Expected.

◆ Expected() [6/9]

ETCPAL_CONSTEXPR_14 Expected ( Expected< U > &&  other,
ETCPAL_ENABLE_IF_ARG( std::is_constructible< T, U >::value && !std::is_constructible< T, Expected< U > & >::value && !std::is_constructible< T, Expected< U > && >::value && !std::is_constructible< T, Expected< U > const & >::value && !std::is_constructible< T, Expected< U > const && >::value && !std::is_convertible< Expected< U > &, T >::value && !std::is_convertible< Expected< U > &&, T >::value && !std::is_convertible< Expected< U > const &, T >::value && !std::is_convertible< Expected< U > const &&, T >::value && !std::is_convertible< U, T >::value  
)
inlineexplicit

Explicit conversion move constructor - enabled for U that can be explicitly converted to T.

If other has a value, moves its value into this Expected. If other does not have a value, copies its error code into this Expected.

◆ Expected() [7/9]

ETCPAL_CONSTEXPR_14 Expected ( Expected< U > &&  other,
ETCPAL_ENABLE_IF_ARG( std::is_constructible< T, U >::value && !std::is_constructible< T, Expected< U > & >::value && !std::is_constructible< T, Expected< U > && >::value && !std::is_constructible< T, Expected< U > const & >::value && !std::is_constructible< T, Expected< U > const && >::value && !std::is_convertible< Expected< U > &, T >::value && !std::is_convertible< Expected< U > &&, T >::value && !std::is_convertible< Expected< U > const &, T >::value && !std::is_convertible< Expected< U > const &&, T >::value && std::is_convertible< U, T >::value  
)
inline

Implicit conversion move constructor - enabled for U that can be implicitly converted to T.

If other has a value, moves its value into this Expected. If other does not have a value, copies its error code into this Expected.

◆ Expected() [8/9]

ETCPAL_CONSTEXPR_14 Expected ( U &&  value,
ETCPAL_ENABLE_IF_ARG(std::is_constructible< T, U && >::value && !std::is_convertible< U &&, T >::value  
)
inlineexplicitnoexcept

Construct from value, explicit.

Constructs an Expected from some value U which is explicitly (but not implicitly) convertible to T. The constructor is made explicit as a result. This Expected instance has a value after this constructor is called.

Parameters
valueValue to construct from.

◆ Expected() [9/9]

ETCPAL_CONSTEXPR_14 Expected ( U &&  value,
ETCPAL_ENABLE_IF_ARG(std::is_constructible< T, U && >::value && std::is_convertible< U &&, T >::value  
)
inlinenoexcept

Construct from value, implicit.

Constructs an Expected from some value U implicitly convertible to T. The constructor is not made explicit as a result. This Expected instance has a value after this constructor is called.

Parameters
valueValue to construct from.

Member Function Documentation

◆ error()

constexpr Error error
constexprnoexcept

Get the error code as a Error object.

If has_value() is true, the behavior is undefined.

◆ error_code()

constexpr etcpal_error_t error_code
constexprnoexcept

Get the error code.

If has_value() is true, the behavior is undefined.

◆ operator*() [1/4]

T & operator* ( ) &

Get the underlying value.

If has_value() is false, the behavior is undefined.

◆ operator*() [2/4]

ETCPAL_CONSTEXPR_14 T && operator* ( ) &&

Get the underlying value.

If has_value() is false, the behavior is undefined.

◆ operator*() [3/4]

constexpr const T & operator* ( ) const &
constexpr

Get the underlying value.

If has_value() is false, the behavior is undefined.

◆ operator*() [4/4]

constexpr const T && operator* ( ) const &&
constexpr

Get the underlying value.

If has_value() is false, the behavior is undefined.

◆ operator->() [1/2]

T * operator->

Access members of a composite contained value.

If has_value() is false, the behavior is undefined.

◆ operator->() [2/2]

constexpr const T * operator->
constexpr

Access members of a composite contained value.

If has_value() is false, the behavior is undefined.

◆ value() [1/4]

T & value ( ) &

Get the underlying value.

Exceptions
BadExpectedAccessif has_value() is false.

◆ value() [2/4]

ETCPAL_CONSTEXPR_14 T && value ( ) &&

Get the underlying value.

Exceptions
BadExpectedAccessif has_value() is false.

◆ value() [3/4]

ETCPAL_CONSTEXPR_14 const T & value ( ) const &

Get the underlying value.

Exceptions
BadExpectedAccessif has_value() is false.

◆ value() [4/4]

ETCPAL_CONSTEXPR_14 const T && value ( ) const &&

Get the underlying value.

Exceptions
BadExpectedAccessif has_value() is false.

◆ value_or() [1/2]

T value_or ( U &&  def_val) &&
inline

Get the value, or a default value if this Expected contains an error.

Parameters
def_valThe default value to return on error - must be convertible to T.

◆ value_or() [2/2]

constexpr T value_or ( U &&  def_val) const &
inlineconstexpr

Get the value, or a default value if this Expected contains an error.

Parameters
def_valThe default value to return on error - must be convertible to T.

The documentation for this class was generated from the following file: