constexpr void swap(expected& rhs) noexcept(see below);
概要
他のexpected
オブジェクトとデータを入れ替える。
動作説明用のexpected
クラスメンバ変数として、下記を導入する。
val
:T
型の正常値。unex
:E
型のエラー値。has_val
:bool
型のフラグ変数。正常値を保持する場合はtrue
に、エラー値を保持する場合はfalse
となる。
テンプレートパラメータ制約
次の制約を全て満たすこと
is_swappable_v<T> == true
is_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++: ??