Skip to content

Commit 2f09aa8

Browse files
committed
concat_viewの解説を追加 #1337
1 parent 3602f00 commit 2f09aa8

File tree

3 files changed

+173
-1
lines changed

3 files changed

+173
-1
lines changed

lang/cpp26.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ C++26とは、2026年中に改訂される予定の、C++バージョンの通
123123
- [`std::unordered_multiset`](/reference/unordered_set/unordered_multiset.md)
124124
- [`bucket()`](/reference/unordered_set/unordered_multiset/bucket.md)
125125
- [`std::span`](/reference/span/span.md)[`std::mdspan`](/reference/mdspan/mdspan.md)の推論補助を改善
126-
- [`std::views::concat`](/reference/ranges/concat_view.md.nolink)を追加
126+
- [`std::views::concat`](/reference/ranges/concat_view.md)を追加
127127

128128

129129
### アルゴリズム

reference/ranges.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,13 @@ range | adaptor(args...)
308308
| [`split_view`](ranges/split_view.md) | 文字列分割に特化した`lazy_split_view` (class template) | C++20 |
309309
| [`views::split`](ranges/split_view.md) | `split_view`を生成する (customization point object) | C++20 |
310310
311+
### concat view
312+
313+
| 名前 | 説明 | 対応バージョン |
314+
|-------------------------------------------------------|--------------------------------------------------------------|----------------|
315+
| [`concat_view`](ranges/concat_view.md) | 複数のRangeを連結するビュー (class template) | C++26 |
316+
| [`views::concat`](ranges/concat_view.md) | `concat_view`を生成する (customization point object) | C++26 |
317+
311318
### counted view
312319
313320
| 名前 | 説明 | 対応バージョン |

reference/ranges/concat_view.md

Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,165 @@
1+
# concat_view
2+
* ranges[meta header]
3+
* std::ranges[meta namespace]
4+
* class template[meta id-type]
5+
* cpp26[meta cpp]
6+
7+
```cpp
8+
namespace std::ranges {
9+
template<input_range... Views>
10+
requires (view<Views> && ...) && (sizeof...(Views) > 0) && concatable<Views...>
11+
class concat_view : public view_interface<concat_view<Views...>> {…… }; // (1)
12+
13+
namespace views {
14+
inline constexpr /*unspecified*/ concat = /*unspecified*/; // (2)
15+
}
16+
}
17+
```
18+
19+
## 概要
20+
21+
`concat_view`は複数のRangeを連結し、1つのRangeとする[`view`](view.md)。
22+
23+
- (1): `concat_view`のクラス定義
24+
- (2): `concat_view`を生成するカスタマイゼーションポイントオブジェクト(Rangeアダプタオブジェクトではない)
25+
26+
### Rangeコンセプト
27+
28+
| borrowed | sized | output | input | forward | bidirectional | random_access | contiguous | common | viewable | view |
29+
|----------|-------|--------|-------|---------|---------------|---------------|------------|--------|----------|------|
30+
| | (1) | 〇 | 〇 | (2) | (3) | (4) | | (5) | ○ | ○ |
31+
32+
- (1): 連結するすべてのRangeが[`sized_range`](sized_range.md)のとき
33+
- (2): 連結するすべてのRangeが[`forward_range`](forward_range.md)のとき
34+
- (3): 連結するすべてのRangeが[`bidirectional_range`](bidirectional_range.md)であり、少なくとも最後のRange以外が[`common_range`](common_range.md)のとき
35+
- (4): 連結するすべてのRangeが[`random_access_range`](random_access_range.md)であり、少なくとも最後のRange以外が[`common_range`](common_range.md)のとき
36+
- (5): 最後のRangeが[`common_range`](common_range.md)のとき
37+
38+
## テンプレートパラメータ制約
39+
40+
連結するすべてのビューに対して、
41+
42+
- それらの要素に共通の値型`Cv`、参照型`Cr`、右辺値参照型`Crr` が存在し、
43+
- `Cr&&`と`Cv&`、`Cr&&`と`Crr&&`、`Crr&&`と`Cv const&`にそれぞれ共通の参照型があり、
44+
- 連結するすべてのビューのイテレーター`it`について、
45+
- `*it`が`Cr`に変換可能であり、
46+
- `ranges::iter_move(it)`が`Crr`に変換可能であること。
47+
48+
## 効果
49+
50+
- (2): 式`views::concat(Es...)`の効果は次の通り
51+
- `Es...`が1要素で、その型が [`input_range`](input_range.md)のモデルであるとき、[`views::all`](all.md)`(Es...)` と等しい
52+
- それ以外のとき、`concat_view(Es...)` と等しい
53+
54+
## 備考
55+
56+
本説明に用いる説明専用要素を以下のように定義する。
57+
58+
```cpp
59+
namespace std::ranges {
60+
template<class... Rs>
61+
using concat-reference-t = common_reference_t<range_reference_t<Rs>...>;
62+
63+
template<class... Rs>
64+
using concat-value-t = common_type_t<range_value_t<Rs>...>;
65+
66+
template<class... Rs>
67+
using concat-rvalue-reference-t = common_reference_t<range_rvalue_reference_t<Rs>...>;
68+
69+
template<class Ref, class RRef, class It>
70+
concept concat-indirectly-readable-impl =
71+
requires (const It it) {
72+
{ *it } -> convertible_to<Ref>;
73+
{ ranges::iter_move(it) } -> convertible_to<RRef>;
74+
};
75+
76+
template<class... Rs>
77+
concept concat-indirectly-readable =
78+
common_reference_with<concat-reference-t<Rs...>&&, concat-value-t<Rs...>&> &&
79+
common_reference_with<concat-reference-t<Rs...>&&, concat-rvalue-reference-t<Rs...>&&> &&
80+
common_reference_with<concat-rvalue-reference-t<Rs...>&&, concat-value-t<Rs...> const&> &&
81+
(concat-indirectly-readable-impl<concat-reference-t<Rs...>, concat-rvalue-reference-t<Rs...>, iterator_t<Rs>> && ...);
82+
83+
template<class... Rs>
84+
concept concatable = requires {
85+
typename concat-reference-t<Rs...>;
86+
typename concat-value-t<Rs...>;
87+
typename concat-rvalue-reference-t<Rs...>;
88+
} && concat-indirectly-readable<Rs...>;
89+
90+
// Fs を Rs の末尾を除いたパックとする
91+
92+
template<bool Const, class... Rs>
93+
concept concat-is-random-access =
94+
all-random-access<Const, Rs...> &&
95+
(common_range<maybe-const<Const, Fs>> && ...);
96+
97+
template<bool Const, class... Rs>
98+
concept concat-is-bidirectional =
99+
all-bidirectional<Const, Rs...> &&
100+
(common_range<maybe-const<Const, Fs>> && ...);
101+
}
102+
```
103+
* all-random-access[link all-random-access.md]
104+
* all-bidirectional[link all-bidirectional.md]
105+
106+
107+
## メンバ関数
108+
109+
| 名前 | 説明 | 対応バージョン |
110+
|--------------------------------------------------|----------------------------------|----------------|
111+
| [`(constructor)`](concat_view/op_constructor.md.nolink) | コンストラクタ | C++26 |
112+
| [`begin`](concat_view/begin.md.nolink) | 先頭を指すイテレータを取得する | C++26 |
113+
| [`end`](concat_view/end.md.nolink) | 番兵を取得する | C++26 |
114+
| [`size`](concat_view/size.md.nolink) | 要素数を取得する | C++26 |
115+
116+
## 継承しているメンバ関数
117+
118+
| 名前 | 説明 | 対応バージョン |
119+
|----------------------------------------------|-----------------------------------|----------------|
120+
| [`empty`](view_interface/empty.md) | Rangeが空かどうかを判定する | C++20 |
121+
| [`operator bool`](view_interface/op_bool.md) | Rangeが空でないかどうかを判定する | C++20 |
122+
| [`front`](view_interface/front.md) | 先頭要素への参照を取得する | C++20 |
123+
| [`back`](view_interface/back.md) | 末尾要素への参照を取得する | C++20 |
124+
| [`cbegin`](view_interface/cbegin.md) | 定数イテレータを取得する | C++23 |
125+
| [`cend`](view_interface/cend.md) | 定数イテレータ(番兵)を取得する | C++23 |
126+
| [`operator[]`](view_interface/op_at.md) | 要素へアクセスする | C++20 |
127+
128+
## 推論補助
129+
130+
| 名前 | 説明 | 対応バージョン |
131+
|-------------------------------------------------------|------------------------------|----------------|
132+
| [`(deduction_guide)`](concat_view/op_deduction_guide.md.nolink) | クラステンプレートの推論補助 | C++23 |
133+
134+
##
135+
```cpp example
136+
import std;
137+
138+
int main() {
139+
std::vector<int> v1{1, 2, 3}, v2{4, 5}, v3{};
140+
std::array a{6, 7, 8};
141+
auto s = std::views::single(9);
142+
std::print("{} ", std::views::concat(v1, v2, v3, a, s));
143+
}
144+
```
145+
* std::views::concat[color ff0000]
146+
* std::views::single[link single_view.md]
147+
148+
### 出力
149+
```
150+
[1, 2, 3, 4, 5, 6, 7, 8, 9]
151+
```
152+
153+
## バージョン
154+
### 言語
155+
- C++26
156+
157+
### 処理系
158+
- [Clang](/implementation.md#clang): ??
159+
- [GCC](/implementation.md#gcc): ??
160+
- [ICC](/implementation.md#icc): ??
161+
- [Visual C++](/implementation.md#visual_cpp): ??
162+
163+
## 参照
164+
- [26.7.18 Concat view](https://timsong-cpp.github.io/cppwp/range.concat) (2024-08-10)
165+
- [P2542R8 views::concat](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2542r8.html)

0 commit comments

Comments
 (0)