Skip to content

Commit

Permalink
flat_map : insert_rangeを追加 #1078
Browse files Browse the repository at this point in the history
  • Loading branch information
faithandbrave committed Aug 17, 2023
1 parent f3f7503 commit 292f841
Show file tree
Hide file tree
Showing 3 changed files with 132 additions and 48 deletions.
2 changes: 1 addition & 1 deletion reference/flat_map/flat_map.md
Expand Up @@ -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 |
Expand Down
58 changes: 11 additions & 47 deletions reference/flat_map/flat_map/insert.md
Expand Up @@ -30,13 +30,10 @@ void insert(sorted_unique_t,
InputIterator first,
InputIterator last); // (8) C++23

template<container-compatible-range<value_type> R>
void insert_range(R&& rg); // (9) C++23

void insert(initializer_list<value_type> il); // (10) C++23
void insert(initializer_list<value_type> il); // (9) C++23

void insert(sorted_unique_t s,
initializer_list<value_type> il); // (11) C++23
initializer_list<value_type> il); // (10) C++23
```
* pair[link /reference/utility/pair.md]
* initializer_list[link /reference/initializer_list/initializer_list.md]
Expand Down Expand Up @@ -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) : ソート済みかつ重複要素のない初期化子リストを挿入する
## 要件
Expand Down Expand Up @@ -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());
```
Expand All @@ -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) : この操作はインプレース・マージを行うため、追加のメモリ確保を行う可能性がある


##
Expand All @@ -263,7 +226,6 @@ int main()
};

// シーケンスを挿入する
fm.insert(fm2);
fm.insert(fm2.begin(), fm2.end());

// 挿入するシーケンスがソート済みかつ重複要素がないことがわかっている場合、
Expand All @@ -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]
Expand All @@ -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) | キーが存在しない場合のみ要素を直接構築する |
Expand Down
120 changes: 120 additions & 0 deletions 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<container-compatible-range<value_type> 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 <iostream>
#include <flat_map>

int main()
{
std::flat_map<int, char> fm = {
{3, 'a'}
};

std::flat_map<int, char> 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) | キーが存在しない場合のみ要素を直接構築する |

0 comments on commit 292f841

Please sign in to comment.