|
| |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Primary template | ||
constexprvoid swap( expected& other)noexcept(/* see below */); | (1) | (since C++23) |
void partial specialization | ||
constexprvoid swap( expected& other)noexcept(/* see below */); | (2) | (since C++23) |
Swaps the contents with those ofother.
Value ofhas_value() | Value ofother.has_value() | |
|---|---|---|
| true | false | |
| true | usingstd::swap; swap( val, rhs.val); | see below |
| false | other.swap(*this); | usingstd::swap; swap( unex, rhs.unex); |
has_value() istrue andother.has_value() isfalse, equivalent to:// Case 1: the move constructions of unexpected values are non-throwing:
// “other.unex” will be restored if the construction of “other.val” fails
ifconstexpr(std::is_nothrow_move_constructible_v<E>)
{ E temp(std::move(other.unex)); std::destroy_at(std::addressof(other.unex)); try { std::construct_at(std::addressof(other.val), std::move(val));// may throw std::destroy_at(std::addressof(val)); std::construct_at(std::addressof(unex), std::move(temp)); } catch(...) { std::construct_at(std::addressof(other.unex), std::move(temp)); throw; }
}
// Case 2: the move constructions of expected values are non-throwing:
// “this->val” will be restored if the construction of “this->unex” fails
else
{ T temp(std::move(val)); std::destroy_at(std::addressof(val)); try { std::construct_at(std::addressof(unex), std::move(other.unex));// may throw std::destroy_at(std::addressof(other.unex)); std::construct_at(std::addressof(other.val), std::move(temp)); } catch(...) { std::construct_at(std::addressof(val), std::move(temp)); throw; }
}has_val =false;
rhs.has_val =true;
Value ofhas_value() | Value ofother.has_value() | |
|---|---|---|
| true | false | |
| true | usingstd::swap; swap( val, rhs.val); | std::construct_at(std::addressof(unex), std::move(rhs.unex));std::destroy_at(std::addressof(rhs. unex));has_val =false;rhs. has_val =true; |
| false | other.swap(*this); | usingstd::swap; swap( unex, rhs.unex); |
Contents |
| other | - | theexpected object to exchange the contents with |
std::is_nothrow_move_constructible_v<E>&&std::is_nothrow_swappable_v<E>
#include <expected>#include <iostream>#include <string_view> using Ex=std::expected<std::string,int>; void show(const Ex& ex1,const Ex& ex2,std::string_view term="\n"){for(int i{}; i!=2;++i){std::cout<<(i?"ex2":"ex1");if(const Ex& ex=(i? ex2: ex1); ex.has_value())std::cout<<".value() = "<<*ex<<" ";elsestd::cout<<".error() = "<< ex.error()<<" ";}std::cout<< term;} int main(){ Ex ex1("\N{CAT FACE}"); Ex ex2{"\N{GREEN HEART}"}; show(ex1, ex2,"after ex1.swap(ex2):\n"); ex1.swap(ex2); show(ex1, ex2,"\n\n"); ex2=std::unexpected(13); show(ex1, ex2,"after ex1.swap(ex2):\n"); ex1.swap(ex2); show(ex1, ex2,"\n\n"); ex2=std::unexpected(37); show(ex1, ex2,"after ex1.swap(ex2):\n"); ex1.swap(ex2); show(ex1, ex2);}
Output:
ex1.value() = 🐱 ex2.value() = 💚 after ex1.swap(ex2):ex1.value() = 💚 ex2.value() = 🐱 ex1.value() = 💚 ex2.error() = 13 after ex1.swap(ex2):ex1.error() = 13 ex2.value() = 💚 ex1.error() = 13 ex2.error() = 37 after ex1.swap(ex2):ex1.error() = 37 ex2.error() = 13
(C++23) | specializes thestd::swap algorithm (function)[edit] |