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

履歴 編集

function
<variant>

std::emplace(C++17)

namespace std {
  template <class T, class... Args>
  T& emplace(Args&&... args);                              // (1)

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

  template <std::size_t I, class... Args>
  variant_alternative_t<I, variant<Types...>>&
    emplace(Args&&... args);                               // (3)

  template <std::size_t I, class U, class... Args>
  variant_alternative_t<I, variant<Types...>>&
    emplace(std::initializer_list<U> il, Args&&... args);  // (4)
}

概要

variantに代入する値を直接構築する。

  • (1) : 候補型に含まれるT型のオブジェクトを、コンストラクタ引数args...から構築して保持する
  • (2) : 候補型に含まれるT型のオブジェクトを、コンストラクタ引数ilargs...から構築して保持する
  • (3) : I番目の候補型オブジェクトを、コンストラクタ引数args...から構築して保持する
  • (4) : I番目の候補型オブジェクトを、コンストラクタ引数ilargs...から構築して保持する

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

事前条件

  • (3), (4) : index()Iであること

効果

  • (1) : Types...に含まれる型TのインデックスをIとして、以下と等価:

    return emplace<I>(std::forward<Args>(args)...);
    

  • (2) : Types...に含まれる型TのインデックスをIとして、以下と等価:

    return emplace<I>(il, std::forward<Args>(args)...);
    

  • (3) :

    • 値を保持している場合、破棄する
    • Types...I番目の型をTiとして、Ti型オブジェクトをコンストラクタ引数std::forward<Args>(args)...で構築して保持する
  • (4) :
    • 値を保持している場合、破棄する
    • Types...I番目の型をTiとして、Ti型オブジェクトをコンストラクタ引数ilstd::forward<Args>(args)...で構築して保持する

戻り値

新たに保持する値への参照を返す。

例外

  • (1), (2), (3), (4) : 保持する値の初期化中に例外が発生する可能性があり、その後、variantオブジェクトは値を保持しない可能性がある

備考

  • この関数は、テンプレート内で使用する場合に、v.template emplace<T>(args...)のようにtemplate限定子を指定する必要がある。

基本的な使い方

#include <cassert>
#include <variant>
#include <string>

int main()
{
  // (1)
  {
    std::variant<int, char, std::string> v;

    // vオブジェクト内でstd::stringオブジェクトを構築して保持
    std::string& s = v.emplace<std::string>(3, 'a');

    assert(s == "aaa");
    assert(std::get<std::string>(v) == "aaa");
  }

  // (2)
  {
    std::variant<int, char, std::string> v;

    std::allocator<char> alloc;
    v.emplace<std::string>({'H', 'e', 'l', 'l', 'o'}, alloc);

    assert(std::get<std::string>(v) == "Hello");
  }

  // (3)
  {
    std::variant<int, char, std::string> v;
    v.emplace<2>(3, 'a');

    assert(std::get<2>(v) == "aaa");
  }

  // (4)
  {
    std::variant<int, char, std::string> v;

    std::allocator<char> alloc;
    v.emplace<2>({'H', 'e', 'l', 'l', 'o'}, alloc);

    assert(std::get<2>(v) == "Hello");
  }
}

出力

同じ型を複数指定できる状況の例

#include <cassert>
#include <variant>
#include <string>

int main()
{
  // インデックスを指定した代入なら、同じ型が複数現れてもよい。
  // 代入演算子、emplace<T>()、std::get<T>()、std::holds_alternative<T>()は使用できない。
  // in_place_index<I>を指定するコンストラクタ、emplace<I>()、std::get<I>(), index()は使用できる
  std::variant<std::string, std::string> v;
  v.emplace<0>("abc"); // OK
  std::string& s = std::get<0>(v);
  assert(s == "abc");

  //v.emplace<std::string>("abc"); // コンパイルエラー!
  //v = "abc"; // コンパイルエラー!
}

出力

バージョン

言語

  • C++17

処理系