Optional Component

The optional component contains several types that store an optional value. Arguably the most well known is the optional type (for which this component is named). optional is available in Boost. However, this implementation of optional follows the revision 5 proposal (N3793) as closely as possible.

In addition to optional, an expected type is provided. This type is based off of a type mentioned by Andrei Alexandrescu in his 2012 talk Systematic Error Handling in C++. Instead of an optional null-state, the expected type contains either a type T, or an exception. It differes significantly from Alexandrescu’s talk in that it’s interface closely resembles optional. It also has the ability to extract the contained exception without the need of a try-catch block placed by the user, as well as the ability to rethrow the contained exception (if any such exception exists). Additionally, a specialization for expected<void> exists, allowing a function that normally returns void, (but one that may throw an exception) to return the error by way of expected.

Lastly, there is a third optional type provided, named result. This type is closely related to expected. However, it does not contain an exception, but rather a std::error_condition. This type was partially inspired by the Rust language’s Result<T, E>. However, the result type is intended to model non-exception, portable error conditions to check against, hence it holding either a instance of type T or a non-zero std::error_condition. Much like expected<void>, a result<void> is also provided to easily allow checking for a non-zero std::error_condition in a function that ideally would return void. This type was provided to allow generic use of result. Technically, this type can be replaced with a std::error_condition. However it removes the ability to mark a function as returning void.

The optional component resides in the <core/optional.hpp> header.

class in_place_t

in_place_t is an empty class type used to disambiguate the overloads and member functions of optional that take arguments (such as optional<T>::emplace()) for in-place construction of some value.

An object of this type is available under the name in_place.

class nullopt_t

nullopt_t is an empty class type used to indicate an optional type with uninitialized state.

An object of this type is available under the name nullopt.

class bad_optional_access
Inherits:std::logic_error

Thrown when accessing an optional that is in a disengaged state.

Note

Accessing an optional in a disengaged state does not refer to accessing the underlying object. Specifically it means calling optional member functions, and not member functions of the underlying object it may or may not currently manage.

class bad_expected_type
Inherits:std::logic_error

Thrown when calling expected<T>::expect(), if the expected type is incorrect. Also thrown when attempting to expect or raise an exception when an expected is in a valid state (that is, it does not currently manage an exception)

class bad_result_condition
Inherits:std::logic_error

Thrown when attempting to access the std::error_condition of a result in a valid state. A result will never contain a std::error_condition with a value of 0, and will only be invalid if it actively manages a std::error_condition.

Optional Type

class optional<T>

The optional manages an optional value. This value may be in either an initialized state, or an uninitialized state. This value is guaranteed to be allocated within the optional. Instead of modelling a pointer, such as std::unique_ptr<T> or std::shared_ptr<T>, optional models an object, even though optional<T>::operator->() and optional<T>::operator*() are provided.

New in version 1.1: optional follows the N3793 proposal. This means optional is now usable as a constexpr-able type. Additionally, optional now has the other comparison operators available. These are implemented in terms of operator == and operator <.

An optional object is engaged when one of the following occurs:

  • The object is initialized with a value of type T
  • The object is assigned an engaged optional.

An optional object is disengaged when one of the following occurs:

  • The object is default-initialized.
  • The object is initialized with an instance of nullopt_t or a disengaged optional.
  • The object is assigned with an instance of nullopt_t or a disengaged optional.
type value_type

Represents the underlying type stored within an optional.

Warning

An optional‘s value_type may not be:

  • in_place_t
  • nullopt_t
  • std::nullptr_t
  • void
  • any type for which std::is_reference<T>::value is true.
  • any type for which std::is_object<T>::value is false
optional(optional const&)

Copies the contents of the incoming optional. If the incoming optional is engaged, the contents of it are initialized into the new optional object.

optional(optional&& that)

Constructs a new optional by moving the state of the incoming optional. If the incoming optional is engaged, its contents will be moved into the new object. The effects of bool(that) remain the same.

Noexcept:std::is_nothrow_move_constructible<value_type>
constexpr optional(nullopt_tr) noexcept
constexpr optional() noexcept

Constructs a new optional in a disengaged state.

constexpr optional(value_type const&)
constexpr optional(value_type&&)

Constructs a new optional into an engaged state with the contents of the value_type.

Noexcept:std::is_nothrow_move_constructible<value_type>
constexpr explicit optional(in_place_t, std::initializer_list<U>, Args)
constexpr explicit optional(in_place_t, Args)

Constructs a new optional into an engaged state by constructing a value_type in place with the variadic arguments Args.

optional& operator=(optional const&)
optional& operator=(optional&&)
Noexcept:std::is_nothrow_move_assignable<value_type> and std::is_nothrow_move_constructible<value_type>.

Assigns the state of the incoming optional. This is done by constructing an optional, and then calling swap() on it and *this.

optional& operator=(T&& value)

This assignment operator is only valid if value_type is constructible and assignable from value.

If *this is disengaged, it will be placed into an engaged state afterwards. If *this is already engaged, it will call the assignment constructor of value_type.

optional& operator=(nullopt_t)

If *this is in an engaged state, it will be placed into a disengaged state.

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

Accessing the managed object when the optional is in a disengaged state will result in undefined behavior.

Returns:pointer to the object managed by the optional
constexpr value_type const& operator*() const
value_type& operator*()

If the optional does not manage an object, dereferencing the optional will result in undefined behavior.

Returns:An lvalue reference to the object managed by the optional
constexpr explicit operator bool() const noexcept
Returns:true if the object is engaged, false otherwise.
constexpr value_type value_or(U&& value) const
value_type value_or(U&& value)

If *this is an lvalue reference the :type`value_type` will be copy constructed. If *this is an rvalue reference, the value_type is move constructed.

Returns:the object managed by optional or a value_type constructed from value.
constexpr value_type const& value() const
value_type& value()
Raises:bad_optional_access
void swap(optional& that)

Swaps the contents of ‘this’ with the given object. The behavior that is taken varies as such:

  • If neither *this, nor that are engaged, this function is a no-op.
  • If only one of either *this and that are engaged, the contained value of the disengaged object is initialized by moving the contained value of the engaged object. This is followed by the destruction of the originally engaged object’s value. The state of both objects has been switched.
  • If both *this and that are engaged, their contained values are swapped with std::swap(**this, *that).
void emplace(std::initializer_list<U>, args)
void emplace(args)

Constructs the object managed by the optional. If the optional is already engaged, it will first destruct the object it is currently managing.

Expected Type

class expected<T>

expected works much like optional in that it contains an optionally instantiated type T. However, unlike optional it is never in a disengaged state. Instead its managed object is either valid or invalid. Like optional it does not model a pointer, but rather an object and provides the pointer access operator overloads for convenience.

Note

expected does not implement the interface proposed in N4015. expected was originally written over a year in advance of the proposal.

An expected object is valid when one of the following occurs:

  • The object is initialized with a value of type T
  • The object is constructed with a valid expected
  • The object is assigned a valid expected
  • The object is default-initialized.

An expected object is invalid when one of the following occurs:

  • The object is initialized with a std::exception_ptr or an invalid expected.
  • The object is assigned a std::exception_ptr or an invalid expected.

New in version 1.1: In addition to operator == and operator <, expected is now comparable via the other relational operators.

type value_type

Represents the given type T.

Warning

An expected‘s value_type may not be:

  • in_place_t
  • nullopt_t
  • std::exception_ptr
  • any type for which std::is_reference<T>::value is true.
  • any type for which std::is_object<T>::value is false.
explicit expected(std::exception_ptr) noexcept

Initializes the expected with the given exception_ptr. The expected is then placed into an invalid state.

expected(value_type const&)
expected(value_type&&)

Initializes the expected with the given value. Afterwards, the expected is in a valid state.

expected(expected const&)
expected(expected&&)

Initializes the expected base on the incoming expected‘s valid state. The state of the incoming expected does not change.

expected()

Default initializes the expected to be in a valid state. This default constructs a expected<T>::value_type inside the expected.

explicit expected(in_place_t, std::initializer_list<U>, Args)
explicit expected(in_place_t, Args)

Constructs a new expected into an engaged state by constructing a value_type in place with the given arguments.

expected& operator=(expected const&)
expected& operator=(expected&&)

Assigns the content of the incoming expected to *this.

expected& operator=(value_type const&)
expected& operator=(value_type&&)

Initializes the expected with the assigned value. If the expected holds an exception_ptr, it is destructed, and the expected<T>::value_type is initialized (not assigned) the incoming value.

expected& operator=(std::exception_ptr)

If the expected is in a valid state, it will be placed into an invalid state.

void swap(expected& that)
Noexcept:std::is_nothrow_move_constructible<value_type and core::is_nothrow_swappable<value_type>.

If both expected are valid, then their values are swapped. If both expected are invalid, then their exception_ptrs are swapped.

Otherwise, the valid and invalid state between both expected is swapped and the valid object is moved into the invalid object, and vice versa.

explicit operator bool() const noexcept
Returns:Whether the expected is valid or invalid.
value_type const* operator->() const noexcept
value_type* operator->() noexcept

Accessing the managed object when the expected is invalid will result in undefined behavior.

New in version 1.1.

Returns:pointer to the object managed by the expected
value_type const& operator*() const noexcept
value_type& operator*() noexcept
Returns:The object managed by the expected. Accessing this object when the expected is invalid will result in undefined behavior.
value_type const& value() const
value_type& value()
Returns:The object managed by expected
Throws:The exception managed by expected if the expected
Noexcept:false
value_type value_or(U&& value) const
value_type value_or(U&& value)
Returns:The object managed by expected if valid, otherwise, value is returned. This function will not compile if U is not convertible to expected<T>::value_type.
void emplace(std::initializer_list<U>, Args)
void emplace(Args)

New in version 1.1.

Constructs the object managed by expected. If the expected is already valid, it will first destruct the object it is currently managing.

E expect() const
Noexcept:false

This function attempts to extract the given exception type E. If expected is valid, bad_expected_type is thrown. If expected is invalid, but E is not the correct exception type, std::nested_exception with bad_expected_type and the actual exception are thrown. Otherwise, the exception is returned by value.

void raise() const
Noexcept:false
Attributes:[[noreturn]].

Throws the expected‘s managed exception if invalid. Otherwise, throws bad_expected_type. This function always throws, and will never return.

std::exception_ptr pointer() const

This function will throw if expected is invalid.

New in version 1.1: Replaces get_ptr().

Returns:The exception pointer managed by expected
Throws:bad_expected_type
Noexcept:false
std::exception_ptr get_ptr() const

Deprecated since version 1.1: Use pointer() as a replacement.

Returns:The exception pointer managed by expected
Throws:bad_expected_type
Noexcept:false

Result Type

class result<T>

New in version 1.1.

result works much like expected. However, it does not manage an exception, but rather a std::error_condition. This is done to provide a nice rounding out for functions which may want to signal an error, but not require the ‘output’ value to be passed by reference or by pointer.

A result object is valid when one of the following occurs:

  • The object is initialized with a value of type T.
  • The object is constructed with a valid result.
  • The object is assigned a valid result.
  • The object is default initialized.
  • The object is constructed with a std::error_condition whose value is 0.
  • The object is assigned a std::error_condition whose value is 0.
A result object is invalid when one of the following occurs:
  • The object is initialized with a non-zero std::error_condition.
  • The object is assigned a non-zero std:error_condition.
type value_type

Represents the given type T.

Warning

A result‘s value_type may not be:

  • in_place_t
  • nullopt_t
  • std::error_condition
  • any type for which std::is_error_condition_enum<T>::value is true
  • any type for which std::is_reference<T>::value is true.
  • any type for which std::is_object<T>::value is false.
  • any type for which std::is_nothrow_destructible<T>::value is false
result(int val, std::error_category const& cat) noexcept
result(std::error_condition const& condition) noexcept
result(ErrorConditionEnum e) noexcept

Initializes the result to be invalid. The third overload may be passed any value for which std::is_error_condition_enum is true.

result(value_type const& value)
result(value_type&& value)

Initializes result into a valid state with the given value. The move constructor is marked noexcept only if std::is_nothrow_move_constructible is true for value_type.

result(in_place_t p, std::initializer<U> il, Args&& args)
result(in_place_t p, Args&& args)

Initializes result into a valid state by constructing a value_type in place with the given arguments. These constructors only participate if value_type is constructible with the given arguments. args is a variadic template of arguments.

result(result const& that)
result(result&& that)

Copies or moves the state stored in that into result as well as its managed value or error condition.

result()

Initializes result into a valid state by default constructing a value_type.

result& operator=(result const& that)
result& operator=(result&& that)

Assigns the contents and state of that to result. If the state of that and result differ, the condition or object managed by result will be destroyed and result‘s state will then be constructed with the data stored in that.

result& operator=(std::error_condition const& condition)
result& operator=(ErrorConditionEnum e)

Assigns the given condition or error condition enum value e to result. If result is in a valid state, its managed object will be destructed, and the incoming value assigned. If condition or e would result in a default constructed value_type, (such as bool(condition) == false), the managed object is still destructed and result will then be assigned a default constructed value_type.

result& operator=(value_type const& value)
result& operator=(value_type&& value)
result& operator=(U&& value)

Assigns value to result. If result is in a valid state, its managed object is also assigned value. If it is in an invalid state, it will then destroy the stored condition, and then place the result into a valid state.

The third overload requires that value_type be assignable and constructible from U.

void swap(result& that)

Swaps the state of that with result. If both that and result are valid, then they swap their managed objects. If both that and result are invalid, they swap their managed conditions. If their states differ, the invalid instance is constructed with the contents of the valid instance via move construction. The valid instance is then invalidated with the previously invalid instance’s condition.

Noexcept:std::is_nothrow_move_constructible<value_type> and core::is_nothrow_swappable<value_type>
explicit operator bool() const noexcept
Returns:Whether result is valid or invalid.
value_type const& operator*() const noexcept
value_type& operator*() noexcept

Calling this function when result is invalid will result in undefined behavior.

Returns:The object managed by result.
value_type const* operator->() const noexcept
value_type* operator->() noexcept

Calling this function when result is invalid will result in undefined behavior.

Returns:The address of the object managed by result
void emplace(std::initializer_list<T> il, Args&& args)
void emplace(Args&& args)

Destroys whatever state is managed by result and then reinitializes it to be valid while constructing a value_type with the given arguments. args is a variadic template argument.

value_type const& value() const
value_type& value()

If result is invalid, this function will throw a std::system_error exception with the managed error condition.

Returns:Object managed by result
Throws:std::system_error
value_type value_or(U&& value) const
value_type value_or(U&& value)

If result is in an invalid state, a value_type converted from value is returned. Otherwise, the result‘s managed object is copied or moved into the returning value, depending on whether result is an rvalue or const lvalue reference.

Requires:value_type be move or copy constructible and that U is convertible to value_type.
Returns:value_type
std::error_condition const& condition() const

If result is invalid, the condition it manages is returned. Otherwise an exception is thrown.

Returns:std::error_condition managed by result
Noexcept:false
Throws:bad_result_condition

Functions

optional<T> make_optional<T>(T&& value)
Raises:Any exceptions thrown by the constructor of T

Creates an optional object from value. Effectively calls:

optional<typename std::decay<T>::type>(std::forward<T>(value));

Due to a bug in Apple Clang-503.0.40, this function is not marked constexpr, and this causes an incompatibility with N3793.

expected<T> make_expected(T&& value)
expected<T> make_expected(E&& exception)
expected<T> make_expected(std::exception_ptr)

New in version 1.1: The overload version which takes exception type E

The first overload returns a valid expected containing a T constructed with value. The second overload returns an invalid expected with an exception_ptr to exception. For this version to be usable, E must inherit from std::exception. The third overload takes an exception pointer and returns an invalid expected from it.

result<T> make_result(T&& value)
result<T> make_result(std::error_condition cnd)
result<T> make_result(ErrorConditionEnum e)

New in version 1.1.

The first overload returns a valid result containing a T constructed with value. The second overload returns an invalid expected with an error_condition. The last overload takes any type for which std::is_error_condition_enum is true.

Operators

bool operator==(optional const&, optional const&) noexcept
bool operator==(optional const&, nullopt_t) noexcept
bool operator==(nullopt_t, optional const&) noexcept
bool operator==(optional<T> const&, T const&) noexcept
bool operator==(T const&, optional<T> const&) noexcept

For the first overload, if only one of the given optional values is engaged, it will return false. If both optional values are disengaged, it will return true. Otherwise the optional values compare their managed objects with operator ==

The second overload returns whether or not the optional value is engaged. The third overload always returns false. The fourth and fifth overloads will check if the optional value is engaged. If it is, the object managed by optional will be compared with operator ==. Otherwise it will return false.

bool operator<(optional<T> const&, optional<T> const&) noexcept
bool operator<(optional<T> const&, nullopt_t) noexcept
bool operator<(nullopt_t, optional<T> const&) noexcept
bool operator<(optional<T> const&, T const&) noexcept
bool operator<(T const&, optional<T> const&) noexcept

For the first overload, if the right optional is disengaged, it will return false. If the left optional is disengaged, it will return true. Otherwise, the result of *lhs < *rhs is returned.

The second overload returns true if the optional is disengaged. The third overload returns true if the optional is engaged. The fourth optional returns true if the optional is disengaged. The fifth optional returns false if the optional is disengaged. Otherwise the result *opt < value or value < *opt is returned.

Note

The rest of the relational operators for optional are (mostly) implemented in terms of operator == and operator <.

bool operator==(expected const&, expected const&) noexcept
bool operator==(expected const&, exception_ptr) noexcept
bool operator==(exception_ptr, expected const&) noexcept
bool operator==(expected const&, T const&) noexcept
bool operator==(T const&, expected const&) noexcept

Changed in version 1.1: The comparison of an expected to an exception_ptr no longer compare the actual underlying exception_ptr if the expected is invalid. Comparing an expected to a std::exception_ptr now works as though one compared an optional to nullopt.

For the first overload if only one of the expected values is valid, it will return false. If both expected values are invalid, it will return true Otherwise, the expected values compare their managed objects with operator ==.

The second and third overload return true if the expected value is invalid.

The fourth and fifth overload returns true only if the expected value is valid and its managed object compares equal wth the T via T‘s operator ==.

bool operator<(expected const&, expected const&) noexcept
bool operator<(expected const&, exception_ptr) noexcept
bool operator<(exception_ptr, expected const&) noexcept
bool operator<(expected const&, T const&) noexcept
bool operator<(T const&, expected const&) noexcept

For the first overload, if the right expected is invalid, it will return false. If the left expected is invalid it will return true. If both expected objects are valid, then their managed values are compared via operator <.

The second overload returns true if the expected is invalid. The third overload returns true if the expected is valid. The fourth overload returns true if the expected is invalid. The fifth overload returns false if the expected is invalid. Otherwise the result of *exp < value or value < *exp is returned.

Note

The rest of the relational operators for expected are implemented in terms of operator == and operator <.

bool operator==(result const&, result const&)
bool operator==(result const&, error_condition const&)
bool operator==(error_condition const&, result const&)
bool operator==(result const&, error_code const&)
bool operator==(error_code const&, result const&)
bool operator==(result const&, T const&)
bool operator==(T const&, result const&)

New in version 1.1.

For the first overload if only one of the result objects is valid, it will return false. If both result objects are invalid, the result of comparing their error_condition is returned. Otherwise, the result values compare via operator ==.

The second, third, fourth, and fifth overload will return false if the result object is valid (even if the std::error_condition or std::error_code were to return false in a boolean context. This was done to minimize issues with differing categories). If the result is invalid, its result<T>::condition() is compared against the std::error_condition or std::error_code via operator ==.

The sixth and seventh overloads will return false if result is invalid. Otherwise the result value is compared with the given T via operator ==.

bool operator<(result const&, result const&)
bool operator<(result const&, error_condition const&)
bool operator<(error_condition const&, result const&)
bool operator<(result const&, T const&)
bool operator<(T const&, result const&)

New in version 1.1.

For the first overload, if both result objects are invalid, the operator < comparison of their result<T>::condition() are returned. If both result objects are valid, the comparison of their values via operator < is returned. If the result on the left is invalid, but the result on the right is not, true is returned. Otherwise false.

The second overload returns false if the result is valid (even if the std::error_condition would evaluate to false in a boolean context. This was done to minimize issues with differing categories). If the result is invalid, its result<T>::condition() is compared against the std::error_condition via operator <

Conversely, the third overload returns true if the result is valid. If the result is invalid, its result<T>::condition() is compared against the std::error_condition via operator <.

For the fourth overload, if the result is invalid, false is returned. Otherwise, the comparison of the result value and T via operator < is returned.

For the fifth overload, if the result is invalid, true is returned. Otherwise, the comparison of the result value and T via operator < is returned.

Note

The rest of the relational operators for result are implemented in terms of operator == and operator <.

Swap

void swap(optional&, optional&)
void swap(expected&, expected&)
void swap(result&, result&)

These swap functions are provided to allow for ADL calls to swap.

Specializations

class expected<void>

expected<void> is provided as a way to have the same semantics as expected, but for functions that do not (or cannot) return a value. Its interface is close to that of expected, however as it cannot store a value, it is smaller and only has member functions related to handling the exception stored within the expected<void>.

type value_type

Always void.

explicit expected(std::exception_ptr) noexcept

Initializes (and invalidates) the expected<void>.

expected(expected const&)
expected(expected&&)

Copies the exception_ptr stored within the expected<void>. Invalidates *this.

expected& operator=(expected const&)
expected& operator=(expected&&)

Copies the exception_ptr stored within the expected<void>. Invalidates *this.

void swap(expected&) noexcept

Swaps the expected<void>‘s exception_ptrs.

explicit operator bool() const noexcept
Returns:Whether the expected<void> is valid or invalid.
E expect<E>() const

See expected<T>::expect<E>()

void raise() const

See expected<T>::raise()

std::exception_ptr pointer() const

Throws if expected<void> is valid.

Returns:The managed exception_ptr if the expected<void> is invalid.
Throws:bad_expected_type if the expected<void> is valid.
Noexcept:false.
std::exception_ptr get_ptr() const

Deprecated since version 1.1: Use pointer() as a replacement.

Returns:The managed exception_ptr if the expected<void> is invalid.
Throws:bad_expected_type if the expected<void> is valid.
Noexcept:false.
class result<void>

result<void> is provided as a way to have the same semantics as result, but for functions that do not (or cannot) return a value. Its interface is close to that of result, however as it cannot store an object, it is smaller and only has member functions related to handling error conditions.

Technically speaking, this type is unnecessary as an error_condition can be supplied instead. However, it’s sometimes nice to allow for more generic code to be written, and worrying about whether or not you might accidentally instantiate a result<void> isn’t something one should have to worry about.

The copy, move, and default constructors as well as the copy and move assignment operators for result<void> are defaulted, letting the stored std::error_condition be managed instead.

type value_type

Always void.

result(int value, std::error_category const& category)
result(std::error_condition cnd)
result(ErrorConditionEnum e)

Constructs the result<void> with the given value. Any type for which std::is_error_condition_enum is true may be used as an argument in the third overload.

result& operator=(std::error_condition const& condition)
result& operator=(ErrorConditionEnum e) noexcept

Assigns result<void> with the given value. Any value for which std::is_error_condition_enum is true may be used in the second overload.

explicit operator bool() const noexcept
Returns:Whether the result<void> is valid or invalid.
void swap(result& that)

Swaps the stored std::error_condition with that.

std::error_condition const& condition() const

If the result<void> is valid, it will throw an exception. Otherwise, the std::error_condition stored will be returned.

Noexcept:false
Throws:bad_result_condition
Returns:The stored std::error_condition if result<void> is invalid.

std::hash

class hash<optional<T>>

Specialization of std::hash.

Requires that the optional<T>::value_type be specialized for std::hash. If the optional is engaged it will return the hash value for hash<value_type>. Otherwise, it will return a default constructed std::hash<value_type>::result_type.

class hash<expected<T>>

Specialization of std::hash.

Requests that the expected<T>::value_type be specialized for std::hash. If the expected is valid, it will return the hash value for hash<value_type>. Otherwise, it will return a default constructed std::hash<value_type>::result_type.

class hash<result<T>>

Specialization of std::hash.

Requests that the result<T>::value_type be specialized for std::hash. If the result is valid, it will return the hash value for hash<value_type>. Otherwise, it will return a default constructed std::hash<value_type>::result_type.