optional<T>& operator=(nullopt_t rhs) noexcept; // (1) C++17
constexpr optional<T>& operator=(nullopt_t rhs) noexcept; // (1) C++23
optional& operator=(const optional& rhs); // (2) C++17
constexpr optional& operator=(const optional& rhs); // (2) C++20
optional& operator=(optional&& rhs) noexcept(see below); // (3) C++17
constexpr optional& operator=(optional&& rhs) noexcept(see below); // (3) C++20
template <class U = T>
optional& operator=(U&& rhs); // (4) C++17
template <class U = T>
constexpr optional& operator=(U&& rhs); // (4) C++23
template <class U>
optional& operator=(const optional<U>& rhs); // (5) C++17
template <class U>
constexpr optional& operator=(const optional<U>& rhs); // (5) C++23
template <class U>
optional& operator=(optional<U>&& rhs); // (6) C++17
template <class U>
constexpr optional& operator=(optional<U>&& rhs); // (6) C++23
// optional<T&>固有のオーバーロード (C++26)
constexpr optional& operator=(const optional&) noexcept = default; // (7) C++26
概要
- (1) : 無効値を代入する
- (2) : コピー代入
- (3) : ムーブ代入
- (4) : 要素型
Tに変換可能な値をムーブ代入 - (5) :
optional<T>に変換可能なoptionalオブジェクトをコピー代入 - (6) :
optional<T>に変換可能なoptionalオブジェクトをムーブ代入 - (7) :
optional<T&>のコピー代入。参照先の再束縛 (rebind) を行う (noexcept = default)
optional<T>では (1)~(6) が定義される。optional<T&>では (1), (7) が定義される。
テンプレートパラメータ制約
- (4), (5), (6) : 型
Uが型Tに変換可能であること
効果
(1)~(6) では、*this と rhs が有効な値を持っているか否かによって以下のような挙動となる。
*this が有効な値を持っている |
*this が有効な値を持っていない |
|
|---|---|---|
rhs が有効な値を持っている |
値の代入が行われる。 | 値の構築が行われる。has_value() は true となる。 |
rhs が有効な値を持っていない |
値の破棄が行われる。has_value() は false となる。 |
何も行われない。 |
なお、(1) では rhs は常に有効な値を持っていないとみなされ、また、(4) では rhs は常に有効な値を持っているとみなされる。
また、rhs が有効な値を持っている場合に operator=(代入の場合)、あるいは、コンストラクタ(構築の場合)を呼び出す際の引数は以下となる。
- (2), (5):
*rhs - (3), (6):
std::move(*rhs) - (4):
std::forward<U>(rhs)
(7) では、rhsが保持する参照先ポインタをコピーする (参照先の再束縛)。
戻り値
*this
例外
共通の動作として、代入演算子内で例外が発生した場合、has_value()の結果は変わらない。
- (2) :
- (3) :
- (4), (5), (6) :
delete定義される条件
- (2) : 型
Tがコピー構築可能でなく、コピー代入可能でもないこと - (3) : 型
Tがムーブ構築可能でなく、ムーブ代入可能でもないこと
トリビアルに定義される条件
- (2) : 型
Tが、トリビアルにコピー構築可能でありトリビアルにコピー代入可能かつ、トリビアルに破棄可能である - (3) : 型
Tが、トリビアルにムーブ構築可能でありトリビアルにムーブ代入可能かつ、トリビアルに破棄可能である
備考
- (7) :
optional<T&>への代入は、参照先オブジェクトへの代入ではなく、参照先の再束縛 (rebind) を行う。これはポインタの代入と同じセマンティクスである optional<T&>では、値の代入や異なる型のoptionalからの変換代入は提供されない。値を代入する場合は、暗黙の変換によるoptional<T&>の構築とコピー代入 (7) を通じて行われる
例
#include <cassert>
#include <optional>
#include <utility>
int main()
{
// (1)
// 無効値を代入
{
std::optional<int> p = 3;
p = std::nullopt;
assert(!p.has_value());
}
// (2)
// コピー代入
{
std::optional<int> a = 3;
std::optional<int> b = 1;
a = b;
assert(a.value() == 1);
}
// (3)
// ムーブ代入
{
std::optional<int> a = 3;
std::optional<int> b = 1;
a = std::move(b);
assert(a.value() == 1);
}
// (4)
// 有効値をコピー代入もしくはムーブ代入
{
std::optional<int> p;
p = 3;
assert(p.has_value());
assert(p.value() == 3);
}
// (5)
// 変換可能なoptionalオブジェクトをコピー代入
{
std::optional<long long> a = 3LL;
std::optional<int> b = 1;
a = b;
assert(a.value() == 1LL);
}
// (6)
// 変換可能なoptionalオブジェクトをムーブ代入
{
std::optional<long long> a = 3LL;
std::optional<int> b = 1;
a = std::move(b);
assert(a.value() == 1LL);
}
}
出力
バージョン
言語
- C++17
処理系
- GCC: 7.2 ✅
- Clang: 4.0.1 ✅
- ICC: ?
- Visual C++: ??