constexpr void swap(expected& rhs) noexcept(see below);
概要
他のexpectedオブジェクトとデータを入れ替える。
動作説明用のexpectedクラスメンバ変数として、下記を導入する。
val:T型の正常値。unex:E型のエラー値。has_val:bool型のフラグ変数。正常値を保持する場合はtrueに、エラー値を保持する場合はfalseとなる。
テンプレートパラメータ制約
次の制約を全て満たすこと
is_swappable_v<T> == trueis_swappable_v<E> == true(is_move_constructible_v<T> && is_move_constructible_v<E>) == true(is_nothrow_move_constructible_v<T> || is_nothrow_move_constructible_v<E>) == true
効果
*thisとrhsそれぞれが正常値/エラー値いずれを保持しているかに応じて、以下の効果を持つ。
*thisとrhsともに正常値を保持していれば、次と等価 :using std::swap; swap(val, rhs.val);*thisとrhsともにエラー値を保持していれば、次と等価 :using std::swap; swap(unex, rhs.unex);*thisがエラー値をrhsが正常値を保持していれば、次と等価 :rhs.swap(*this);*thisが正常値をrhsがエラー値を保持していれば、次と等価 :
if constexpr (is_nothrow_move_constructible_v<E>) { E tmp(std::move(rhs.unex)); destroy_at(addressof(rhs.unex)); try { construct_at(addressof(rhs.val), std::move(val)); destroy_at(addressof(val)); construct_at(addressof(unex), std::move(tmp)); } catch(...) { construct_at(addressof(rhs.unex), std::move(tmp)); throw; } } else { T tmp(std::move(val)); destroy_at(addressof(val)); try { construct_at(addressof(unex), std::move(rhs.unex)); destroy_at(addressof(rhs.unex)); construct_at(addressof(rhs.val), std::move(tmp)); } catch (...) { construct_at(addressof(val), std::move(tmp)); throw; } } has_val = false; rhs.has_val = true;
戻り値
なし
例外
noexcept例外指定は次の式に従う :
is_nothrow_move_constructible_v<T> && is_nothrow_swappable_v<T> && is_nothrow_move_constructible_v<E> && is_nothrow_swappable_v<E>
noexcept例外指定がfalseの場合、上記の「効果」による処理からの例外が送出される。
例
#include <cassert>
#include <expected>
#include <string>
int main()
{
std::expected<int, std::string> x = 42;
std::expected<int, std::string> y = std::unexpected{"ERR"};
assert(x.value() == 42 && y.error() == "ERR");
x.swap(y);
assert(x.error() == "ERR" && y.value() == 42);
}
出力
バージョン
言語
- C++23
処理系
- Clang: 16.0 ✅
- GCC: 12.1 ✅
- ICC: ??
- Visual C++: ??