From 292f841f9c90af75b5804ce5481dc23e6f93580a Mon Sep 17 00:00:00 2001 From: Akira Takahashi Date: Thu, 17 Aug 2023 16:33:34 +0900 Subject: [PATCH] =?UTF-8?q?flat=5Fmap=20:=20insert=5Frange=E3=82=92?= =?UTF-8?q?=E8=BF=BD=E5=8A=A0=20#1078?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- reference/flat_map/flat_map.md | 2 +- reference/flat_map/flat_map/insert.md | 58 ++-------- reference/flat_map/flat_map/insert_range.md | 120 ++++++++++++++++++++ 3 files changed, 132 insertions(+), 48 deletions(-) create mode 100644 reference/flat_map/flat_map/insert_range.md diff --git a/reference/flat_map/flat_map.md b/reference/flat_map/flat_map.md index 53e8f472e..24660156e 100644 --- a/reference/flat_map/flat_map.md +++ b/reference/flat_map/flat_map.md @@ -60,7 +60,7 @@ namespace std { | [`clear`](flat_map/clear.md) | 全ての要素を削除する | C++23 | | [`insert`](flat_map/insert.md) | 要素を挿入する | C++23 | | [`insert_or_assign`](flat_map/insert_or_assign.md.nolink) | 要素を挿入、あるいは代入する | C++23 | -| [`insert_range`](flat_map/insert_range.md.nolink) | Rangeを挿入する | C++23 | +| [`insert_range`](flat_map/insert_range.md) | Rangeを挿入する | C++23 | | [`emplace`](flat_map/emplace.md) | 要素を直接構築する | C++23 | | [`emplace_hint`](flat_map/emplace_hint.md) | ヒントを使って要素を直接構築する | C++23 | | [`try_emplace`](flat_map/try_emplace.md) | キーが存在しない場合のみ要素を直接構築する | C++23 | diff --git a/reference/flat_map/flat_map/insert.md b/reference/flat_map/flat_map/insert.md index 5f3a656f0..e19ee2fba 100644 --- a/reference/flat_map/flat_map/insert.md +++ b/reference/flat_map/flat_map/insert.md @@ -30,13 +30,10 @@ void insert(sorted_unique_t, InputIterator first, InputIterator last); // (8) C++23 -template R> -void insert_range(R&& rg); // (9) C++23 - -void insert(initializer_list il); // (10) C++23 +void insert(initializer_list il); // (9) C++23 void insert(sorted_unique_t s, - initializer_list il); // (11) C++23 + initializer_list il); // (10) C++23 ``` * pair[link /reference/utility/pair.md] * initializer_list[link /reference/initializer_list/initializer_list.md] @@ -64,9 +61,8 @@ void insert(sorted_unique_t s, - (6) : 指定された位置に、要素型`value_type`のコンストラクタ引数を受け取って挿入する - (7) : イテレータ範囲`[first, last)`を挿入する - (8) : ソート済みかつ重複要素のないイテレータ範囲`[first, last)`を挿入する -- (9) : Rangeを挿入する -- (10) : 初期化子リストを挿入する -- (11) : ソート済みかつ重複要素のない初期化子リストを挿入する +- (9) : 初期化子リストを挿入する +- (10) : ソート済みかつ重複要素のない初期化子リストを挿入する ## 要件 @@ -181,44 +177,12 @@ void insert(sorted_unique_t s, * key_equiv[link key_equiv.md] * distance[link /reference/iterator/distance.md] -- (9) : メンバ変数として保持しているコンテナ`c`に、以下のように挿入する: - ```cpp - for (const auto& e : rg) { - c.keys.insert(c.keys.end(), e.first); - c.values.insert(c.values.end(), e.second); - } - ``` - * c.keys[link containers.md] - * c.values[link containers.md] - * end()[link /reference/vector/vector/end.md] - * insert[link /reference/vector/vector/insert.md] - * first[link /reference/utility/pair.md] - * second[link /reference/utility/pair.md] - - - 次に、新しく挿入された要素の範囲を`value_comp()`を基準にソートする - - 次に、ソートされた結果の範囲と、既存の要素のソートされた範囲をひとつのソートされた範囲にマージする - - 最後に、重複する要素を以下のように削除する: - - ```cpp - auto zv = ranges::zip_view(c.keys, c.values); - auto it = ranges::unique(zv, key_equiv(compare)).begin(); - auto dist = distance(zv.begin(), it); - c.keys.erase(c.keys.begin() + dist, c.keys.end()); - c.values.erase(c.values.begin() + dist, c.values.end()); - ``` - * c.keys[link containers.md] - * c.values[link containers.md] - * ranges::zip_view[link /ranges/zip_view.md.nolink] - * ranges::unique[link /reference/algorithm/ranges_unique.md] - * key_equiv[link key_equiv.md] - * distance[link /reference/iterator/distance.md] - -- (10) : +- (9) : ```cpp insert(il.begin(), il.end()); ``` -- (11) : +- (10) : ```cpp insert(s, il.begin(), il.end()); ``` @@ -231,17 +195,16 @@ void insert(sorted_unique_t s, - (3), (4), (6) : - 挿入された場合には、新しく挿入された要素を指すイテレータを返す。 - 挿入されなかった場合には、`x`のキーと等価のキーを持つ要素へのイテレータを返す。 -- (7), (8), (9), (10), (11) : なし +- (7), (8), (9), (10) : なし ## 計算量 - (7) : Nをこの操作の前の[`size()`](size.md)、Mを[`distance`](/reference/iterator/distance.md)`(first, last)`として、N + MlogM -- (7) : Nをこの操作のあとの[`size()`](size.md)として、Nに対して線形 -- (8) : Nをこの操作の前の[`size()`](size.md)、Mを[`ranges::distance`](/reference/iterator/ranges_distance.md)`(rg)`として、N + MlogM +- (8) : Nをこの操作のあとの[`size()`](size.md)として、Nに対して線形 ## 備考 -- (7), (8), (9) : この操作はインプレース・マージを行うため、追加のメモリ確保を行う可能性がある +- (7), (8) : この操作はインプレース・マージを行うため、追加のメモリ確保を行う可能性がある ## 例 @@ -263,7 +226,6 @@ int main() }; // シーケンスを挿入する - fm.insert(fm2); fm.insert(fm2.begin(), fm2.end()); // 挿入するシーケンスがソート済みかつ重複要素がないことがわかっている場合、 @@ -275,6 +237,7 @@ int main() } } ``` +* insert[color ff0000] * begin()[link begin.md] * end()[link end.md] * std::sorted_unique[link /reference/flat_map/sorted_unique_t.md] @@ -298,6 +261,7 @@ int main() | 名前 | 説明 | |------------------------------------------------|--------------------------------------------| | [`flat_map::insert_or_assign`](insert_or_assign.md.nolink) | 要素を挿入、あるいは代入する | +| [`flat_map::insert_range`](insert_range.md) | Rangeを挿入する | | [`flat_map::emplace`](emplace.md) | 要素を直接構築する | | [`flat_map::emplace_hint`](emplace_hint.md) | ヒントを使って要素を直接構築する | | [`flat_map::try_emplace`](try_emplace.md) | キーが存在しない場合のみ要素を直接構築する | diff --git a/reference/flat_map/flat_map/insert_range.md b/reference/flat_map/flat_map/insert_range.md new file mode 100644 index 000000000..7962278bf --- /dev/null +++ b/reference/flat_map/flat_map/insert_range.md @@ -0,0 +1,120 @@ +# insert_range +* flat_map[meta header] +* std[meta namespace] +* flat_map[meta class] +* function[meta id-type] +* cpp23[meta cpp] + +```cpp +template R> +void insert_range(R&& rg); // (1) C++23 +``` +* container-compatible-range[link /reference/exposition-only/container-compatible-range.md] + +## 概要 +Rangeを挿入し、コンテナを拡張する。 + +これは、挿入された要素の数だけコンテナの [`size()`](size.md) を増やす。 + +`flat_map` コンテナは重複したキーを持つ要素を許さないため、挿入操作はそれぞれの要素が他のコンテナ内の既存要素と同じキーかどうかをチェックする。もし同じであれば要素は挿入されない。 + +重複した値を許す、類似したコンテナについては `flat_multimap` を参照。 + +内部的に `flat_map` コンテナは、コンストラクト時に指定された比較オブジェクトによって要素を下位から上位へとソートして保持する。 + + +## 効果 +- メンバ変数として保持しているコンテナ`c`に、以下のように挿入する: + ```cpp + for (const auto& e : rg) { + c.keys.insert(c.keys.end(), e.first); + c.values.insert(c.values.end(), e.second); + } + ``` + * c.keys[link containers.md] + * c.values[link containers.md] + * end()[link /reference/vector/vector/end.md] + * insert[link /reference/vector/vector/insert.md] + * first[link /reference/utility/pair.md] + * second[link /reference/utility/pair.md] + + - 次に、新しく挿入された要素の範囲を`value_comp()`を基準にソートする + - 次に、ソートされた結果の範囲と、既存の要素のソートされた範囲をひとつのソートされた範囲にマージする + - 最後に、重複する要素を以下のように削除する: + + ```cpp + auto zv = ranges::zip_view(c.keys, c.values); + auto it = ranges::unique(zv, key_equiv(compare)).begin(); + auto dist = distance(zv.begin(), it); + c.keys.erase(c.keys.begin() + dist, c.keys.end()); + c.values.erase(c.values.begin() + dist, c.values.end()); + ``` + * c.keys[link containers.md] + * c.values[link containers.md] + * ranges::zip_view[link /ranges/zip_view.md.nolink] + * ranges::unique[link /reference/algorithm/ranges_unique.md] + * key_equiv[link key_equiv.md] + * distance[link /reference/iterator/distance.md] + + +## 戻り値 +なし + + +## 計算量 +- Nをこの操作の前の[`size()`](size.md)、Mを[`ranges::distance`](/reference/iterator/ranges_distance.md)`(rg)`として、N + MlogM + + +## 備考 +- この操作はインプレース・マージを行うため、追加のメモリ確保を行う可能性がある + + +## 例 +```cpp example +#include +#include + +int main() +{ + std::flat_map fm = { + {3, 'a'} + }; + + std::flat_map fm2 = { + {5, 'd'}, + {15, 'e'} + }; + + fm.insert_range(fm2); + + for (const auto& [key, value] : fm) { + std::cout << key << " : " << value << std::endl; + } +} +``` +* insert_range[color ff0000] + +### 出力 +``` +3 : a +5 : d +15 : e +``` + +## バージョン +### 処理系 +- [Clang](/implementation.md#clang): ?? +- [GCC](/implementation.md#gcc): ?? +- [Visual C++](/implementation.md#visual_cpp): ?? + + +## 関連項目 + +| 名前 | 説明 | +|------------------------------------------------|--------------------------------------------| +| [`flat_map::insert`](insert.md) | 要素を挿入する | +| [`flat_map::insert_or_assign`](insert_or_assign.md.nolink) | 要素を挿入、あるいは代入する | +| [`flat_map::emplace`](emplace.md) | 要素を直接構築する | +| [`flat_map::emplace_hint`](emplace_hint.md) | ヒントを使って要素を直接構築する | +| [`flat_map::try_emplace`](try_emplace.md) | キーが存在しない場合のみ要素を直接構築する | +