template <class... Args>
pair<iterator, bool>
try_emplace(const key_type& k,
Args&&... args); // (1) C++17
template <class... Args>
pair<iterator, bool>
try_emplace(key_type&& k,
Args&&... args); // (2) C++17
template<class K, class... Args>
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>
iterator
try_emplace(const_iterator hint,
key_type&& k,
Args&&... args); // (5) C++17
template<class K, class... Args>
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>のバージョンが追加された
- C++26で