// expected<cv void, E>部分特殊化
constexpr expected& operator=(const expected& rhs); // (1)
constexpr expected& operator=(expected&& rhs) noexcept(see below); // (2)
template<class G>
constexpr expected& operator=(const unexpected<G>& e); // (3)
template<class G>
constexpr expected& operator=(unexpected<G>&& e); // (4)
概要
- (1) : コピー代入。
- (2) : ムーブ代入。
- (3) : 変換可能な
unexpected
オブジェクトから、エラー値としてコピー代入。 - (4) : 変換可能な
unexpected
オブジェクトから、エラー値としてムーブ代入。
動作説明用のexpected
クラスメンバ変数として、下記を導入する。
unex
:E
型のエラー値。has_val
:bool
型のフラグ変数。正常値を保持する場合はtrue
に、エラー値を保持する場合はfalse
となる。
テンプレートパラメータ制約
- (3) : 次の制約を全て満たすこと
is_constructible_v<E, const G&> == true
is_assignable_v<E&, const G&> == true
- (4) : 次の制約を全て満たすこと
is_constructible_v<E, G> == true
is_assignable_v<E&, G> == true
効果
- (1) : 次の処理と等価
this
とrhs
が共に正常値を保持していたら、なにもしないthis
が正常値を保持し、rhs
がエラー値を保持していたら、construct_at(addressof(unex), rhs.unex); has_value = false;
this
がエラーを保持し、rhs
が正常値を保持していたら、unex
を破棄しhas_value = true;
this
とrhs
が共にエラー値を保持していたら、unex = rhs.error()
- (2) : 次の処理と等価
this
とrhs
が共に正常値を保持していたら、なにもしないthis
が正常値を保持し、rhs
がエラー値を保持していたら、construct_at(addressof(unex), std::move(rhs.unex)); has_value = false;
this
がエラーを保持し、rhs
が正常値を保持していたら、unex
を破棄しhas_value = true;
this
とrhs
が共にエラー値を保持していたら、unex = std::move(rhs.error())
- (3) : 次の処理と等価
this
が正常値を保持していたら、construct_at(addressof(unex), val, std::forward<const G&>(e.error())); has_val = false;
this
がエラー値を保持していたら、unex = std::forward<const G&>(e.error());
- (4) : 次の処理と等価
this
が正常値を保持していたら、construct_at(addressof(unex), val, std::forward<G>(e.error())); has_val = false;
this
がエラー値を保持していたら、unex = std::forward<G>(e.error());
戻り値
*this
例外
- (2) : ムーブ代入演算子のnoexcept例外指定は、次の式に従う
is_nothrow_move_constructible_v<E> && is_nothrow_move_assignable_v<E>
delete定義される条件
- (1) : 下記いずれか1つでも満たされないとき、コピー代入演算子はdelete定義される。
is_copy_assignable_v<E> == true
is_copy_constructible_v<E> == true
例
#include <cassert>
#include <expected>
#include <memory>
#include <string>
#include <tuple>
#include <utility>
// std::pair型から2要素std::tuple型へはコピー代入可能
using IntPair = std::pair<int, int>;
using IntTuple = std::tuple<int, int>;
// std::unique_ptr型からstd::shared_ptr型へはムーブ代入可能
using UniquePtr = std::unique_ptr<int>;
using SharedPtr = std::shared_ptr<int>;
int main()
{
// (1) コピー代入
{
std::expected<void, int> srcV;
std::expected<void, int> dstV;
dstV = srcV;
assert(srcV.has_value() && dstV.has_value());
std::expected<void, int> srcE = std::unexpected{42};
std::expected<void, int> dstE;
dstE = srcE;
assert(!srcE.has_value() && !dstE.has_value());
assert(srcE.error() == 42 && dstE.error() == 42);
}
// (2) ムーブ代入
{
std::expected<void, std::string> srcV;
std::expected<void, std::string> dstV;
dstV = std::move(srcV);
assert(srcV.has_value() && dstV.has_value());
std::expected<void, std::string> srcE = std::unexpected{"Oops"};
std::expected<void, std::string> dstE;
dstE = std::move(srcE);
assert(!srcE.has_value() && !dstE.has_value());
assert(dstE.error() == "Oops");
// srcE.error()はstd::stringムーブ後の未規定の値
}
// (3) エラー値の変換コピー代入
{
std::unexpected<IntPair> src{IntPair{1, 2}};
std::expected<void, IntTuple> dst;
dst = src;
assert(not dst.has_value());
assert((dst.error() == IntTuple{1, 2}));
}
// (4) エラー値の変換ムーブ代入
{
std::unexpected<UniquePtr> src{std::make_unique<int>(42)};
std::expected<void, SharedPtr> dst;
dst = std::move(src);
assert(not dst.has_value());
assert(*dst.error() == 42);
}
}
xxxxxxxxxx
#include <cassert>
#include <expected>
#include <memory>
#include <string>
#include <tuple>
#include <utility>
// std::pair型から2要素std::tuple型へはコピー代入可能
using IntPair = std::pair<int, int>;
using IntTuple = std::tuple<int, int>;
// std::unique_ptr型からstd::shared_ptr型へはムーブ代入可能
using UniquePtr = std::unique_ptr<int>;
using SharedPtr = std::shared_ptr<int>;
int main()
{
// (1) コピー代入
出力
バージョン
言語
- C++23
処理系
- Clang: 16.0 ✅
- GCC: 12.1 ✅
- ICC: ??
- Visual C++: ??