最終更新日時(UTC):
が更新

履歴 編集

function
<optional>

std::optional::operator=(C++17)

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) では、*thisrhs が有効な値を持っているか否かによって以下のような挙動となる。

*this が有効な値を持っている *this が有効な値を持っていない
rhs が有効な値を持っている 値の代入が行われる。 値の構築が行われる。has_value()true となる。
rhs が有効な値を持っていない 値の破棄が行われる。has_value()false となる。 何も行われない。

なお、(1) では rhs は常に有効な値を持っていないとみなされ、また、(4) では rhs は常に有効な値を持っているとみなされる。

また、rhs が有効な値を持っている場合に operator=(代入の場合)、あるいは、コンストラクタ(構築の場合)を呼び出す際の引数は以下となる。

(7) では、rhsが保持する参照先ポインタをコピーする (参照先の再束縛)。

戻り値

*this

例外

共通の動作として、代入演算子内で例外が発生した場合、has_value()の結果は変わらない。

  • (2) :
    • Tのコピーコンストラクタで例外が発生した場合は、なにも効果がなく終了する。型Tのコピー代入で例外が発生した場合は、型Tのコピー代入演算子の例外安全性が保証する動作となる
  • (3) :
    • 要素型Tが、ムーブ代入とムーブ構築で例外を送出しない場合、この関数は決して例外を送出しない
    • Tのムーブコンストラクタで例外が発生した場合、*rhs.valの状態は型Tのムーブコンストラクタの例外安全性によって決定される
  • (4), (5), (6) :
    • Tのコンストラクタもしくは代入演算子で例外が発生した場合、それらの関数の例外安全性が保証する動作となる

delete定義される条件

  • (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

処理系

参照