|
6 | 6 |
|
7 | 7 | ```cpp |
8 | 8 | 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 |
16 | 42 | } |
17 | 43 | ``` |
18 | 44 | * input_iterator[link /reference/iterator/input_iterator.md] |
@@ -116,19 +142,22 @@ concept indirectly-binary-left-foldable = |
116 | 142 | 入力範囲`r`(`[first, last)`)の要素数を`N`とすると、正確に`N`回の`f`の適用が行われる。 |
117 | 143 |
|
118 | 144 | ## 備考 |
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 | + ``` |
132 | 161 |
|
133 | 162 | ## 例 |
134 | 163 |
|
@@ -172,7 +201,7 @@ int main() { |
172 | 201 | * plus[link /reference/functional/plus.md] |
173 | 202 | * println[link /reference/print/println.md] |
174 | 203 |
|
175 | | -### 出力 |
| 204 | +#### 出力 |
176 | 205 | ``` |
177 | 206 | 55 |
178 | 207 | 1.125 |
@@ -217,12 +246,36 @@ int main() { |
217 | 246 | * println[link /reference/print/println.md] |
218 | 247 | * fold_right[link ranges_fold_right.md] |
219 | 248 |
|
220 | | -### 出力 |
| 249 | +#### 出力 |
221 | 250 | ``` |
222 | 251 | init -> a -> b -> c -> d -> e -> f |
223 | 252 | init -> f -> e -> d -> c -> b -> a |
224 | 253 | ``` |
225 | 254 |
|
| 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 | + |
226 | 279 | ## 実装例 |
227 | 280 |
|
228 | 281 | ```cpp |
@@ -273,3 +326,5 @@ constexpr auto fold_left(I first, S last, T init, F f) { |
273 | 326 |
|
274 | 327 | - [P2322R6 `ranges::fold`](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p2322r6.html) |
275 | 328 | - [プログラミング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で波カッコ初期化 (リスト初期化) に対応した |
0 commit comments