最終更新日時: 2026年02月17日 23時22分33秒 (JST)
Akira Takahashi が更新

履歴 編集

function template
<unordered_map>

# std::unordered_map::try_emplace(C++17)

    template <class... Args>
    pair<iterator, bool>
      try_emplace(const key_type& k,
                  Args&&... args); // (1) C++17
    template <class... Args>
    constexpr pair<iterator, bool>
      try_emplace(const key_type& k,
                  Args&&... args); // (1) C++26

    template <class... Args>
    pair<iterator, bool>
      try_emplace(key_type&& k,
                  Args&&... args); // (2) C++17
    template <class... Args>
    constexpr pair<iterator, bool>
      try_emplace(key_type&& k,
                  Args&&... args); // (2) C++26

    template<class K, class... Args>
    constexpr pair<iterator, bool>
      try_emplace(K&& k,
                  Args&&... args); // (3) C++26

    template <class... Args>
    iterator
      try_emplace(const_iterator hint,
                  const key_type& k,
                  Args&&... args); // (4) C++17
    template <class... Args>
    constexpr iterator
      try_emplace(const_iterator hint,
                  const key_type& k,
                  Args&&... args); // (4) C++26

    template <class... Args>
    iterator
      try_emplace(const_iterator hint,
                  key_type&& k,
                  Args&&... args); // (5) C++17
    template <class... Args>
    constexpr iterator
      try_emplace(const_iterator hint,
                  key_type&& k,
                  Args&&... args); // (5) C++26

    template<class K, class... Args>
    constexpr iterator
      try_emplace(const_iterator hint,
                  K&& k,
                  Args&&... args); // (6) C++26

## 概要

引数 `k` と等価のキーを持つ要素が存在しない場合、コンテナに新しい要素を挿入する。要素は引数からコンテナ内に直接構築されるため、構築されたオブジェクトはコピーもムーブもされない。
なお、本メンバ関数は `emplace` や `emplace_hint` 等と異なり、引数 `k` と等価のキーを持つ要素が既に存在する場合には、`k` や `args` がムーブされてしまうことはない。

引数 `hint` は、`k` を検索する際のヒントに使用される。（が、実際に使用されることはないものと思われる。`emplace_hint` の備考を参照）

- (1) : キーをコピーし、値型のコンストラクタ引数をとり直接構築して、新たな要素を挿入する
- (2) : キーをムーブし、値型のコンストラクタ引数をとり直接構築して、新たな要素を挿入する
- (3) : `key_type`型と比較可能なキーを転送し、値型のコンストラクタ引数をとり直接構築して、新たな要素を挿入する
- (4) : 検索位置のヒントを受け取ってキーをコピーし、値型のコンストラクタ引数をとり直接構築して、新たな要素を挿入する
- (5) : 検索位置のヒントを受け取ってキーをムーブし、値型のコンストラクタ引数をとり直接構築して、新たな要素を挿入する
- (6) : 検索位置のヒントを受け取って`key_type`型と比較可能なキーをムーブし、値型のコンストラクタ引数をとり直接構築して、新たな要素を挿入する

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

- (1), (3), (4), (6) : `value_type` は、`piecewise_construct`, `forward_as_tuple(k)`, `forward_as_tuple(forward<Args>(args)...)` から `unordered_map` に直接構築可能であること
- (2), (5) : `value_type` は、`piecewise_construct`, `forward_as_tuple(move(k))`, `forward_as_tuple(forward<Args>(args)...)` から `unordered_map` に直接構築可能であること
- (3), (6) :
  - `key_compare::is_transparent` が妥当な式であること
  - `is_convertible_v<K&&, const_iterator> == false`であること
  - `is_convertible_v<K&&, iterator> == false`であること

なお、規格に記載はないが、`hint` は `emplace_hint` と同様、コンテナの有効な読み取り専用イテレータである必要があるものと思われる。

## 効果

- (1), (3), (4), (6) : `unordered_map` が `k` と同値のキーを持つ要素を持っている場合、何もしない（引数への副作用もない）。そうでなければ、`piecewise_construct`, `forward_as_tuple(k)`, `forward_as_tuple(forward<Args>(args)...)` から構築した `value_type` 型のオブジェクトを挿入する。
- (2), (5) : `unordered_map` が `k` と同値のキーを持つ要素を持っている場合、何もしない（引数への副作用もない）。そうでなければ、`piecewise_construct`, `forward_as_tuple(move(k))`, `forward_as_tuple(forward<Args>(args)...)` から構築した `value_type` 型のオブジェクトを挿入する。

## 戻り値

- (1), (2), (3) : イテレータと `bool` 値の `pair` を返す。
  - 挿入された場合には、`first` に挿入された要素へのイテレータ、`second` に `true` が設定される。
  - 挿入されなかった場合には、`first` に `k` と等価のキーを持つ既存の要素へのイテレータ、`second` に `false` が設定される。
- (4), (5), (6) :
  - 挿入された場合には、挿入された要素へのイテレータを返す。
  - 挿入されなかった場合には、`k` と等価のキーを持つ既存の要素へのイテレータを返す。

## 計算量

- (1), (2) : `emplace` と同じ。
- (4), (5) : `emplace_hint` と同じ。

## 備考

- 概要に記載されているように、本メンバ関数は指定されたキーと等価の要素が既に存在する場合には、引数に副作用が発生しない。
  - 一方、`emplace`、`emplace_hint`、`insert` にはそのような規定は無く、挿入がされなかった場合でも引数に副作用（引数からのムーブ）が発生してしまう可能性があるため、注意が必要である。
- 規格にはこの関数の例外安全性についての記載が無いが、`emplace` や `emplace_hint` と等価と考えて問題ないと思われる。
- 規格にはこの関数が呼ばれた後のイテレータや要素へのポインタ・参照の有効性についての記載が無いが、`emplace` や `emplace_hint` と等価と考えて問題ないと思われる。
- (3), (6) :
  - `is_transparent`は、標準ライブラリの`std::less`、`std::greater`といった関数オブジェクトの、`void`に対する特殊化で定義される。それ以外のテンプレートパラメータで`is_transparent`が定義されないのは、互換性のためである。
  - これらのオーバーロードは、`map<string, int>`のようなコンテナに対し、検索操作で文字列リテラルを渡した際に、キー型の一時オブジェクトが生成されるコストを減らすためにある。

## 例

    #include <iostream>
    #include <unordered_map>
    #include <string>
    #include <utility>
    #include <memory>

    template <typename T>
    void print(const T& t, bool u)
    {
      std::cout << "key = " << t.first->first << ", value = " << *t.first->second
        << ", is inserted = " << t.second << ", is empty = " << u << '\n';
    }

    int main()
    {
      std::unordered_map<std::string, std::unique_ptr<int>> um;
      std::cout << std::boolalpha;

      auto u1 = std::make_unique<int>(1);
      auto p1 = um.try_emplace("one", std::move(u1));
      print(p1, !u1);

      auto u2 = std::make_unique<int>(2);
      auto p2 = um.try_emplace("two", std::move(u2));
      print(p2, !u2);

      auto u3 = std::make_unique<int>(42);
      auto p3 = um.try_emplace("two", std::move(u3));
      print(p3, !u3);
    }

### 出力

    key = one, value = 1, is inserted = true, is empty = true
    key = two, value = 2, is inserted = true, is empty = true
    key = two, value = 2, is inserted = false, is empty = false

## バージョン

### 言語

- C++17

### 処理系

- Clang: 3.7.0 ✅
- GCC: 6.1.0 ✅
- ICC: ??
- Visual C++: ??

## 関連項目

名前 | 説明
--- | ---
`emplace` | コンテナ内への要素の直接構築
`emplace_hint` | 挿入位置のヒントを使用したコンテナ内への要素の直接構築
`insert` | 要素の追加
`insert_or_assign` | 要素の追加、あるいは代入
`erase` | 要素の削除
`clear` | 全要素の削除
`swap` | 内容の交換
`bucket_count` | バケット数の取得
`load_factor` | 現在の負荷率（バケットあたりの要素数の平均）を取得
`max_load_factor` | 負荷率の最大値を取得、設定
`rehash` | 最小バケット数指定によるバケット数の調整
`reserve` | 最小要素数指定によるバケット数の調整

## 参照

- N4006 An improved emplace() for unique-key maps
- N4240 Improved insertion interface for unique-key maps (Revision 2)
- N4279 Improved insertion interface for unique-key maps (Revision 2.3)
- P2363R5: Extending associative containers with the remaining heterogeneous overloads
  - C++26で`template <class K>`のバージョンが追加された
- P3372R3 constexpr containers and adaptors