最終更新日時: 2026年04月07日 15時36分39秒 (JST)
Akira Takahashi が更新

履歴 編集

function template
<optional>

# std::optional::emplace(C++17)

    // optional<T>版のオーバーロード
    template <class... Args>
    T& emplace(Args&&... args);                                        // (1) C++17
    template <class... Args>
    constexpr T& emplace(Args&&... args);                              // (1) C++23

    template <class U, class... Args>
    T& emplace(std::initializer_list<U> il, Args&&... args);           // (2) C++17
    template <class U, class... Args>
    constexpr T& emplace(std::initializer_list<U> il, Args&&... args); // (2) C++23

    // optional<T&>版のオーバーロード (C++26)
    template <class U>
    constexpr T& emplace(U&& u) noexcept(see below);                   // (3) C++26

## 概要

要素型のコンストラクタ引数から直接構築する。

- (1) : 可変個の引数をとり、それを型`T`のコンストラクタ引数として渡して、この関数内で型`T`の有効値を構築して保持する
- (2) : 初期化子リストと可変個の引数をとり、それらを型`T`のコンストラクタ引数として渡して、この関数内で型`T`の有効値を構築して保持する
- (3) : `optional<T&>`の参照先を再束縛する。変換可能な単一引数を受け取る

`optional<T>`では (1), (2) が定義され、`optional<T&>`では (3) のみが定義される。

## テンプレートパラメータ制約

- (1) : `is_constructible_v<T, Args&&...> == true`であること
- (3) : `is_constructible_v<T&, U> == true`であり、`reference_constructs_from_temporary_v<T&, U> == false`であること

## 効果

- (1), (2) : まず`reset()`メンバ関数を呼び出す
  - (1) : 型`T`の有効値を、`std::forward<Args>(args)...`を引数として構築する
  - (2) : 型`T`の有効値を、`il`と`std::forward<Args>(args)...`を引数として構築する
- (3) : 参照先を`u`に再束縛する

## 戻り値

代入された有効値への参照を返す。

## 例外

型`T`の選択されたコンストラクタが、任意の例外を送出する可能性がある。

## 例外安全性

型`T`のコンストラクタが例外を送出した場合、`*this`は有効値を含まない状態となり、元々保持していた有効値は破棄される。

## 備考

- (2) : このオーバーロードは主に、コンテナをアロケータ付きで、初期化子リスト代入するためにある
- (3) : 一時オブジェクトから参照を構築するとダングリングになるケースでは、このオーバーロードは削除定義される

## 例

    #include <iostream>
    #include <optional>
    #include <string>
    #include <vector>

    int main()
    {
      // (1)
      {
        std::optional<std::string> p;

        // std::stringのコンストラクタ引数を渡して、
        // emplace関数内でstringオブジェクトを構築する。
        p.emplace(3, 'A');
        std::cout << "(1) : " << p.value() << std::endl;
      }

      // (2)
      {
        std::optional<std::vector<int>> p;

        // 初期化子リストとアロケータから、
        // emplace関数内でvectorオブジェクトを構築する。
        std::allocator<int> alloc;
        p.emplace({3, 1, 4}, alloc);

        std::cout << "(2) :" << std::endl;
        for (int x : p.value()) {
          std::cout << "  " << x << std::endl;
        }
      }
    }

### 出力

    (1) : AAA
    (2) :
      3
      1
      4

## バージョン

### 言語

- C++17

### 処理系

- Clang: 4.0.1 ✅
- GCC: 7.2 ✅
- ICC: ??
- Visual C++: ??

## 参照

- N3406 A proposal to add a utility class to represent optional objects (Revision 2)
- LWG Issue 2857. {`variant`,`optional`,`any`}`::emplace` should return the constructed value
- P0084R2 Emplace Return Type (Revision 2)
- P2231R1 Missing `constexpr` in `std::optional` and `std::variant`
- P2988R12 `std::optional<T&>`
  - C++26で参照型`T&`に対する部分特殊化を追加