Skip to content

Commit 18c5fd3

Browse files
committed
fold関係 : C++26波カッコ初期化に対応 #1311
1 parent 93b8c47 commit 18c5fd3

File tree

3 files changed

+225
-57
lines changed

3 files changed

+225
-57
lines changed

reference/algorithm/ranges_fold_left.md

Lines changed: 77 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,39 @@
66

77
```cpp
88
namespace std::ranges {
9-
template<input_iterator I, sentinel_for<I> S, class T,
10-
indirectly-binary-left-foldable<T, I> F>
11-
constexpr auto fold_left(I first, S last, T init, F f); // (1)
12-
13-
template<input_range R, class T,
14-
indirectly-binary-left-foldable<T, iterator_t<R>> F>
15-
constexpr auto fold_left(R&& r, T init, F f); // (2)
9+
template <input_iterator I,
10+
sentinel_for<I> S,
11+
class T,
12+
indirectly-binary-left-foldable<T, I> F>
13+
constexpr auto
14+
fold_left(I first,
15+
S last,
16+
T init,
17+
F f); // (1) C++23
18+
template <input_iterator I,
19+
sentinel_for<I> S,
20+
class T = iter_value_t<I>,
21+
indirectly-binary-left-foldable<T, I> F>
22+
constexpr auto
23+
fold_left(I first,
24+
S last,
25+
T init,
26+
F f); // (1) C++26
27+
28+
template <input_range R,
29+
class T,
30+
indirectly-binary-left-foldable<T, iterator_t<R>> F>
31+
constexpr auto
32+
fold_left(R&& r,
33+
T init,
34+
F f); // (2) C++23
35+
template <input_range R,
36+
class T = range_value_t<R>,
37+
indirectly-binary-left-foldable<T, iterator_t<R>> F>
38+
constexpr auto
39+
fold_left(R&& r,
40+
T init,
41+
F f); // (2) C++26
1642
}
1743
```
1844
* input_iterator[link /reference/iterator/input_iterator.md]
@@ -116,19 +142,22 @@ concept indirectly-binary-left-foldable =
116142
入力範囲`r`(`[first, last)`)の要素数を`N`とすると、正確に`N`回の`f`の適用が行われる。
117143

118144
## 備考
119-
120-
この関数の戻り値型は、入力の型`F, T, I`から次のような`U`として取得される
121-
122-
```cpp
123-
using U = decay_t<invoke_result_t<F&, T, iter_reference_t<I>>>;
124-
```
125-
* decay_t[link /reference/type_traits/decay.md]
126-
* invoke_result_t[link /reference/type_traits/invoke_result.md]
127-
* iter_reference_t[link /reference/iterator/iter_reference_t.md]
128-
129-
すなわち、指定した二項演算を初期値とイテレータによって`f(std::move(init), *first)`のように呼び出した時の戻り値型がこの関数の戻り値型となる。
130-
131-
また、この型`U``fold_left`の処理内部で積算値の型として使用されるものでもあり、`f``init`の代わりに`U`の右辺値も受け取れる必要がある。二項演算の呼び出しにおいては、第一引数に初期値もしくは積算値が渡され、第二引数にイテレータの間接参照結果が直接渡される。そして、二項演算の適用結果は積算値を保存する変数に直接代入される(つまり、結果を次のステップに引き継ぎたい場合は積算処理も二項演算内で行う必要がある)。詳細は下の実装例を参照。
145+
- この関数の戻り値型は、入力の型`F, T, I`から次のような`U`として取得される
146+
```cpp
147+
using U = decay_t<invoke_result_t<F&, T, iter_reference_t<I>>>;
148+
```
149+
* decay_t[link /reference/type_traits/decay.md]
150+
* invoke_result_t[link /reference/type_traits/invoke_result.md]
151+
* iter_reference_t[link /reference/iterator/iter_reference_t.md]
152+
153+
- すなわち、指定した二項演算を初期値とイテレータによって`f(std::move(init), *first)`のように呼び出した時の戻り値型がこの関数の戻り値型となる。
154+
- また、この型`U`は`fold_left`の処理内部で積算値の型として使用されるものでもあり、`f`は`init`の代わりに`U`の右辺値も受け取れる必要がある。二項演算の呼び出しにおいては、第一引数に初期値もしくは積算値が渡され、第二引数にイテレータの間接参照結果が直接渡される。そして、二項演算の適用結果は積算値を保存する変数に直接代入される(つまり、結果を次のステップに引き継ぎたい場合は積算処理も二項演算内で行う必要がある)。詳細は下の実装例を参照。
155+
- (1), (2) :
156+
- C++26 : 引数として波カッコ初期化`{}`を受け付ける
157+
```cpp
158+
std::vector<T> v;
159+
T sum = std::ranges::fold_left(v, {a, b}, op);
160+
```
132161

133162
##
134163

@@ -172,7 +201,7 @@ int main() {
172201
* plus[link /reference/functional/plus.md]
173202
* println[link /reference/print/println.md]
174203
175-
### 出力
204+
#### 出力
176205
```
177206
55
178207
1.125
@@ -217,12 +246,36 @@ int main() {
217246
* println[link /reference/print/println.md]
218247
* fold_right[link ranges_fold_right.md]
219248

220-
### 出力
249+
#### 出力
221250
```
222251
init -> a -> b -> c -> d -> e -> f
223252
init -> f -> e -> d -> c -> b -> a
224253
```
225254

255+
### 波カッコ初期化を入力として使用する (C++26)
256+
```cpp example
257+
#include <algorithm>
258+
#include <print>
259+
#include <vector>
260+
261+
int main() {
262+
std::vector<int> v = {1, 2, 3};
263+
264+
int sum = std::ranges::fold_left(
265+
v,
266+
{},
267+
[](auto&& a, auto&& b) { return a + b; }
268+
);
269+
std::println("{}", sum);
270+
}
271+
```
272+
* std::ranges::fold_left[color ff0000]
273+
274+
#### 出力
275+
```
276+
6
277+
```
278+
226279
## 実装例
227280

228281
```cpp
@@ -273,3 +326,5 @@ constexpr auto fold_left(I first, S last, T init, F f) {
273326
274327
- [P2322R6 `ranges::fold`](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2322r6.html)
275328
- [プログラミングHaskellのfoldr, foldlの説明が秀逸だった件 - あと味](https://taiju.hatenablog.com/entry/20130202/1359773888)
329+
- [P2248R8 Enabling list-initialization for algorithms](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2248r8.html)
330+
- C++26で波カッコ初期化 (リスト初期化) に対応した

reference/algorithm/ranges_fold_left_with_iter.md

Lines changed: 70 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,39 @@
66

77
```cpp
88
namespace std::ranges {
9-
template<input_iterator I, sentinel_for<I> S, class T,
10-
indirectly-binary-left-foldable<T, I> F>
11-
constexpr auto fold_left_with_iter(I first, S last, T init, F f); // (1)
12-
13-
template<input_range R, class T,
14-
indirectly-binary-left-foldable<T, iterator_t<R>> F>
15-
constexpr auto fold_left_with_iter(R&& r, T init, F f); // (2)
9+
template <input_iterator I,
10+
sentinel_for<I> S,
11+
class T,
12+
indirectly-binary-left-foldable<T, I> F>
13+
constexpr auto
14+
fold_left_with_iter(I first,
15+
S last,
16+
T init,
17+
F f); // (1) C++23
18+
template <input_iterator I,
19+
sentinel_for<I> S,
20+
class T = iter_value_t<I>,
21+
indirectly-binary-left-foldable<T, I> F>
22+
constexpr auto
23+
fold_left_with_iter(I first,
24+
S last,
25+
T init,
26+
F f); // (1) C++26
27+
28+
template <input_range R,
29+
class T,
30+
indirectly-binary-left-foldable<T, iterator_t<R>> F>
31+
constexpr auto
32+
fold_left_with_iter(R&& r,
33+
T init,
34+
F f); // (2) C++23
35+
template <input_range R,
36+
class T = range_value_t<R>,
37+
indirectly-binary-left-foldable<T, iterator_t<R>> F>
38+
constexpr auto
39+
fold_left_with_iter(R&& r,
40+
T init,
41+
F f); // (2) C++26
1642
}
1743
```
1844
* input_iterator[link /reference/iterator/input_iterator.md]
@@ -96,10 +122,15 @@ constexpr fold_left_with_iter_result<borrowed_iterator_t<R>, U>
96122
入力範囲`r`(`[first, last)`)の要素数を`N`とすると、正確に`N`回の`f`の適用が行われる。
97123
98124
## 備考
125+
- 戻り値の項で使用している`U`は、指定した二項演算を初期値とイテレータによって`f(std::move(init), *first)`のように呼び出した時の戻り値型であり、`fold_left_with_iter()`の処理内部で積算値の型として使用されるものでもある。
126+
- `fold_left`同様に、`f`は`init`の代わりに`U`の右辺値も受け取れる必要がある。二項演算の呼び出しにおいては、第一引数に初期値もしくは積算値が渡され、第二引数にイテレータの間接参照結果が直接渡される。そして、二項演算の適用結果は積算値を保存する変数に直接代入される(つまり、結果を次のステップに引き継ぎたい場合は積算処理も二項演算内で行う必要がある)。詳細は下の実装例を参照。
127+
- (1), (2) :
128+
- C++26 : 引数として波カッコ初期化`{}`を受け付ける
129+
```cpp
130+
std::vector<T> v;
131+
auto [end, sum] = std::ranges::fold_left_with_iter(v, {a, b}, op);
132+
```
99133
100-
戻り値の項で使用している`U`は、指定した二項演算を初期値とイテレータによって`f(std::move(init), *first)`のように呼び出した時の戻り値型であり、`fold_left_with_iter()`の処理内部で積算値の型として使用されるものでもある。
101-
102-
`fold_left`同様に、`f`は`init`の代わりに`U`の右辺値も受け取れる必要がある。二項演算の呼び出しにおいては、第一引数に初期値もしくは積算値が渡され、第二引数にイテレータの間接参照結果が直接渡される。そして、二項演算の適用結果は積算値を保存する変数に直接代入される(つまり、結果を次のステップに引き継ぎたい場合は積算処理も二項演算内で行う必要がある)。詳細は下の実装例を参照。
103134
104135
## 例
105136
@@ -141,7 +172,7 @@ int main() {
141172
* plus[link /reference/functional/plus.md]
142173
* println[link /reference/print/println.md]
143174

144-
### 出力
175+
#### 出力
145176
```
146177
{ true, 55 }
147178
{ true, 1.125 }
@@ -178,7 +209,7 @@ int main() {
178209
* println[link /reference/print/println.md]
179210
* value_or[link /reference/optional/optional/value_or.md]
180211
181-
### 出力
212+
#### 出力
182213
```
183214
-1
184215
-1
@@ -222,13 +253,37 @@ int main() {
222253
* subrange[link /reference/ranges/subrange.md]
223254
* println[link /reference/print/println.md]
224255

225-
### 出力
256+
#### 出力
226257

227258
```
228259
sum = 36
229260
mul = 36288, 36288
230261
```
231262

263+
### 波カッコ初期化を入力として使用する (C++26)
264+
```cpp example
265+
#include <algorithm>
266+
#include <print>
267+
#include <vector>
268+
269+
int main() {
270+
std::vector<int> v = {1, 2, 3};
271+
272+
auto [end, sum] = std::ranges::fold_left_with_iter(
273+
v,
274+
{},
275+
[](auto&& a, auto&& b) { return a + b; }
276+
);
277+
std::println("{} {}", end == v.end(), sum);
278+
}
279+
```
280+
* std::ranges::fold_left_with_iter[color ff0000]
281+
282+
#### 出力
283+
```
284+
true 6
285+
```
286+
232287
## 実装例
233288

234289
```cpp
@@ -282,3 +337,5 @@ constexpr auto fold_left_with_iter(I first, S last, T init, F f) -> fold_left_wi
282337
## 参照
283338
284339
- [P2322R6 `ranges::fold`](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2322r6.html)
340+
- [P2248R8 Enabling list-initialization for algorithms](https://open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2248r8.html)
341+
- C++26で波カッコ初期化 (リスト初期化) に対応した

0 commit comments

Comments
 (0)