|
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Primary template | ||
constexpr expected& operator=(const expected& other); | (1) | (since C++23) |
constexpr expected& operator=( expected&& other) noexcept(/* see below */); | (2) | (since C++23) |
template<class U=std::remove_cv_t<T>> constexpr expected& operator=( U&& v); | (3) | (since C++23) |
template<class G> constexpr expected& operator=(conststd::unexpected<G>& e); | (4) | (since C++23) |
template<class G> constexpr expected& operator=(std::unexpected<G>&& e); | (5) | (since C++23) |
void partial specialization | ||
constexpr expected& operator=(const expected& other); | (6) | (since C++23) |
constexpr expected& operator=( expected&& other) noexcept(/* see below */); | (7) | (since C++23) |
template<class G> constexpr expected& operator=(conststd::unexpected<G>& e); | (8) | (since C++23) |
template<class G> constexpr expected& operator=(std::unexpected<G>&& e); | (9) | (since C++23) |
Helper function template | ||
template<class T,class U,class...Args> constexprvoid/*reinit-expected*/( T& newval, U& oldval, Args&&...args) | (10) | (since C++23) (exposition only*) |
Assigns a new value to an existingexpected object.
Contents |
| other | - | anotherexpected object whose contained value to assign |
| v | - | value to assign to the contained value |
| e | - | std::unexpected object whose contained value to assign |
| newval | - | the contained value to be constructed |
| oldval | - | the contained value to be destroyed |
| args | - | the arguments used as initializers ofnewval |
has_value() andrhs.has_value() have different values (i.e. one of*this andother contains an expected valueval and the other contains an unexpected valueunex ), the exposition-only function templatereinit-expected is called to safely update the state.Value ofhas_value() | Value ofother.has_value() | |
|---|---|---|
| true | false | |
| true | val =*other; | reinit-expected (unex, val, other.error()); |
| false | reinit-expected (val, unex,*other); | unex = other.error(); |
Value ofhas_value() | Value ofother.has_value() | |
|---|---|---|
| true | false | |
| true | val = std::move(*other); | reinit-expected (unex, val, std::move(other.error())); |
| false | reinit-expected (val, unex, std::move(*other)); | unex = std::move(other.error()); |
has_val = other.has_value();.Value ofhas_value() | Equivalent to |
|---|---|
| true | val =std::forward<U>(v); |
| false | reinit-expected(val, unex,std::forward<U>(v));has_val =false; |
| Overload | Value ofhas_value() | Equivalent to |
|---|---|---|
| (4) | true | reinit-expected(val, unex,std::forward<const G&>(e.error()));has_val =false; |
| false | unex =std::forward<const G&>(e.error()); | |
| (5) | true | reinit-expected(val, unex,std::forward<G>(e.error()));has_val =false; |
| false | unex =std::forward<G>(e.error()); |
Value ofhas_value() | Value ofother.has_value() | |
|---|---|---|
| true | false | |
| true | (no effects) | std::construct_at (std::addressof(unex), rhs.unex);has_val =false; |
| false | std::destroy_at(std::addressof(unex));has_val =true; | unex = other.error(); |
Value ofhas_value() | Value ofother.has_value() | |
|---|---|---|
| true | false | |
| true | (no effects) | std::construct_at (std::addressof(unex), std::move(rhs.unex));has_val =false; |
| false | std::destroy_at(std::addressof(unex));has_val =true; | unex = std::move(other.error()); |
| Overload | Value ofhas_value() | Equivalent to |
|---|---|---|
| (8) | true | std::construct_at(std::addressof(unex), std::forward<const G&>(e.error()));has_val =false; |
| false | unex =std::forward<const G&>(e.error()); | |
| (9) | true | std::construct_at(std::addressof(unex),std::forward<G>(e.error()));has_val =false; |
| false | unex =std::forward<G>(e.error()); |
The exposition-only function templatereinit-expected is “defined” as follows:
template<class NewType,class OldType,class...Args>constexprvoid reinit-expected(NewType& new_val, OldType& old_val, Args&&...args){// Case 1: the construction of “new_val” is non-throwing:// “new_val” can be directly constructed after destroying “old_val”ifconstexpr(std::is_nothrow_constructible_v<NewType, Args...>){std::destroy_at(std::addressof(old_val));std::construct_at(std::addressof(new_val),std::forward<Args>(args)...);}// Case 2: the move construction of “new_val” is non-throwing:// constuct a temporary NewType object first// (“old_val” is left intact if an exception is thrown from this construction)elseifconstexpr(std::is_nothrow_move_constructible_v<NewType>){ NewType temp(std::forward<Args>(args)...);// may throwstd::destroy_at(std::addressof(old_val));std::construct_at(std::addressof(new_val), std::move(temp));}// Case 3: the construction of “new_val” is potentially-throwing:// a backup of “old_val” is required in order to recover from an exceptionelse{ OldType temp(std::move(old_val));// may throwstd::destroy_at(std::addressof(old_val));try{std::construct_at(std::addressof(new_val),std::forward<Args>(args)...);// may throw}catch(...){std::construct_at(std::addressof(old_val), std::move(temp));throw;}}}
This function template is called when the assignment is going to make*this hold the alternative value (i.e. from expected value to unexpected value, or from unexpected value to expected value).
In this case, the old valueoldval needs to be destroyed before constructing the new valuenewval. However, the construction ofnewval may throw an exception. In order to providestrong exception safety guarantee, the old value needs to be restored before rethrowing the exception so that*this will have a valid state while the exception is being handled.
std::unexpected.| This section is incomplete Reason: no example |
The following behavior-changing defect reports were applied retroactively to previously published C++ standards.
| DR | Applied to | Behavior as published | Correct behavior |
|---|---|---|---|
| LWG 3886 | C++23 | the default template argument of overload(3) wasT | changed tostd::remove_cv_t<T> |
| LWG 4025 | C++23 | overload(7) was defined as deleted ifE is notmove constructible or not move assignable | it does not participate in overload resolution in this case |
| constructs the expected value in-place (public member function)[edit] |