88
99// <algorithm>
1010
11- // UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
12-
13- // MSVC warning C4244: 'argument': conversion from 'double' to 'const int', possible loss of data
14- // ADDITIONAL_COMPILE_FLAGS(cl-style-warnings): /wd4244
15-
1611// template<input_iterator I, sentinel_for<I> S, class T,
17- // indirectly-binary-left-foldable<T, I> F>
18- // constexpr see below ranges::fold_left_with_iter(I first, S last, T init, F f);
19- //
20- // template<input_range R, class T, indirectly-binary-left-foldable<T, iterator_t<R>> F>
21- // constexpr see below ranges::fold_left_with_iter(R&& r, T init, F f);
12+ // indirectly-binary-left-foldable<T, I> F>
13+ // constexpr auto fold_left(I first, S last, T init, F f); // since C++23
2214
23- // template<input_iterator I, sentinel_for<I> S, class T,
24- // indirectly-binary-left-foldable<T, I> F>
25- // constexpr see below ranges::fold_left(I first, S last, T init, F f);
26- //
2715// template<input_range R, class T, indirectly-binary-left-foldable<T, iterator_t<R>> F>
28- // constexpr see below ranges::fold_left(R&& r, T init, F f);
16+ // constexpr auto fold_left(R&& r, T init, F f); // since C++23
17+
18+ // REQUIRES: std-at-least-c++23
19+
20+ // MSVC warning C4244: 'argument': conversion from 'double' to 'const int', possible loss of data
21+ // ADDITIONAL_COMPILE_FLAGS(cl-style-warnings): /wd4244
2922
3023#include < algorithm>
3124#include < cassert>
3932#include < string_view>
4033#include < string>
4134#include < vector>
42- #include < optional>
4335
4436#include " test_macros.h"
4537#include " test_range.h"
5042# include < sstream>
5143#endif
5244
53- using std::ranges::fold_left;
54- using std::ranges::fold_left_first;
55- using std::ranges::fold_left_first_with_iter;
56- using std::ranges::fold_left_with_iter;
57-
5845template <class Result , class Range , class T >
5946concept is_in_value_result =
6047 std::same_as<Result, std::ranges::fold_left_with_iter_result<std::ranges::iterator_t <Range>, T>>;
6148
62- template <class Result , class T >
63- concept is_dangling_with = std::same_as<Result, std::ranges::fold_left_with_iter_result<std::ranges::dangling, T>>;
64-
6549struct Integer {
6650 int value;
6751
@@ -76,108 +60,43 @@ template <std::ranges::input_range R, class T, class F, std::equality_comparable
7660 requires std::copyable<R>
7761constexpr void check_iterator (R& r, T const & init, F f, Expected const & expected) {
7862 {
79- is_in_value_result<R, Expected> decltype (auto ) result = fold_left_with_iter (r.begin (), r.end (), init, f);
80- assert (result.in == r.end ());
81- assert (result.value == expected);
82- }
83-
84- {
85- auto telemetry = invocable_telemetry ();
86- auto f2 = invocable_with_telemetry (f, telemetry);
87- is_in_value_result<R, Expected> decltype (auto ) result = fold_left_with_iter (r.begin (), r.end (), init, f2);
88- assert (result.in == r.end ());
89- assert (result.value == expected);
90- assert (telemetry.invocations == std::ranges::distance (r));
91- assert (telemetry.moves == 0 );
92- assert (telemetry.copies == 1 );
93- }
94-
95- {
96- std::same_as<Expected> decltype (auto ) result = fold_left (r.begin (), r.end (), init, f);
63+ std::same_as<Expected> decltype (auto ) result = std::ranges::fold_left (r.begin (), r.end (), init, f);
9764 assert (result == expected);
9865 }
9966
10067 {
10168 auto telemetry = invocable_telemetry ();
10269 auto f2 = invocable_with_telemetry (f, telemetry);
103- std::same_as<Expected> decltype (auto ) result = fold_left (r.begin (), r.end (), init, f2);
70+ std::same_as<Expected> decltype (auto ) result = std::ranges:: fold_left (r.begin (), r.end (), init, f2);
10471 assert (result == expected);
10572 assert (telemetry.invocations == std::ranges::distance (r));
10673 assert (telemetry.moves == 0 );
10774 assert (telemetry.copies == 1 );
10875 }
10976}
11077
111- template <std::ranges::input_range R, class F , std::equality_comparable Expected>
112- requires std::copyable<R>
113- constexpr void check_iterator (R& r, F f, std::optional<Expected> const & expected) {
114- {
115- is_in_value_result<R, std::optional<Expected>> decltype (auto ) result =
116- fold_left_first_with_iter (r.begin (), r.end (), f);
117- assert (result.in == r.end ());
118- assert (result.value == expected);
119- }
120-
121- {
122- auto telemetry = invocable_telemetry ();
123- auto f2 = invocable_with_telemetry (f, telemetry);
124- is_in_value_result<R, std::optional<Expected>> decltype (auto ) result =
125- fold_left_first_with_iter (r.begin (), r.end (), f2);
126- assert (result.in == r.end ());
127- assert (result.value == expected);
128- if (result.value .has_value ()) {
129- assert (telemetry.invocations == std::ranges::distance (r) - 1 );
130- assert (telemetry.moves == 0 );
131- assert (telemetry.copies == 1 );
132- }
133- }
134-
135- {
136- std::same_as<std::optional<Expected>> decltype (auto ) result = fold_left_first (r.begin (), r.end (), f);
137- assert (result == expected);
138- }
139-
140- {
141- auto telemetry = invocable_telemetry ();
142- auto f2 = invocable_with_telemetry (f, telemetry);
143- std::same_as<std::optional<Expected>> decltype (auto ) result = fold_left_first (r.begin (), r.end (), f2);
144- assert (result == expected);
145- if (result.has_value ()) {
146- assert (telemetry.invocations == std::ranges::distance (r) - 1 );
147- assert (telemetry.moves == 0 );
148- assert (telemetry.copies == 1 );
149- }
150- }
151- }
152-
15378template <std::ranges::input_range R, class T , class F , std::equality_comparable Expected>
15479 requires std::copyable<R>
15580constexpr void check_lvalue_range (R& r, T const & init, F f, Expected const & expected) {
156- {
157- is_in_value_result<R, Expected> decltype (auto ) result = fold_left_with_iter (r, init, f);
158- assert (result.in == r.end ());
159- assert (result.value == expected);
160- }
161-
16281 {
16382 auto telemetry = invocable_telemetry ();
16483 auto f2 = invocable_with_telemetry (f, telemetry);
165- std::same_as<Expected> decltype (auto ) result = fold_left (r, init, f2);
84+ std::same_as<Expected> decltype (auto ) result = std::ranges:: fold_left (r, init, f2);
16685 assert (result == expected);
16786 assert (telemetry.invocations == std::ranges::distance (r));
16887 assert (telemetry.moves == 0 );
16988 assert (telemetry.copies == 1 );
17089 }
17190
17291 {
173- std::same_as<Expected> decltype (auto ) result = fold_left (r, init, f);
92+ std::same_as<Expected> decltype (auto ) result = std::ranges:: fold_left (r, init, f);
17493 assert (result == expected);
17594 }
17695
17796 {
17897 auto telemetry = invocable_telemetry ();
17998 auto f2 = invocable_with_telemetry (f, telemetry);
180- std::same_as<Expected> decltype (auto ) result = fold_left (r, init, f2);
99+ std::same_as<Expected> decltype (auto ) result = std::ranges:: fold_left (r, init, f2);
181100 assert (result == expected);
182101 assert (telemetry.invocations == std::ranges::distance (r));
183102 assert (telemetry.moves == 0 );
@@ -188,34 +107,17 @@ constexpr void check_lvalue_range(R& r, T const& init, F f, Expected const& expe
188107template <std::ranges::input_range R, class T , class F , std::equality_comparable Expected>
189108 requires std::copyable<R>
190109constexpr void check_rvalue_range (R& r, T const & init, F f, Expected const & expected) {
191- {
192- auto r2 = r;
193- is_dangling_with<Expected> decltype (auto ) result = fold_left_with_iter (std::move (r2), init, f);
194- assert (result.value == expected);
195- }
196-
197- {
198- auto telemetry = invocable_telemetry ();
199- auto f2 = invocable_with_telemetry (f, telemetry);
200- auto r2 = r;
201- is_dangling_with<Expected> decltype (auto ) result = fold_left_with_iter (std::move (r2), init, f2);
202- assert (result.value == expected);
203- assert (telemetry.invocations == std::ranges::distance (r));
204- assert (telemetry.moves == 0 );
205- assert (telemetry.copies == 1 );
206- }
207-
208110 {
209111 auto r2 = r;
210- std::same_as<Expected> decltype (auto ) result = fold_left (std::move (r2), init, f);
112+ std::same_as<Expected> decltype (auto ) result = std::ranges:: fold_left (std::move (r2), init, f);
211113 assert (result == expected);
212114 }
213115
214116 {
215117 auto telemetry = invocable_telemetry ();
216118 auto f2 = invocable_with_telemetry (f, telemetry);
217119 auto r2 = r;
218- std::same_as<Expected> decltype (auto ) result = fold_left (std::move (r2), init, f2);
120+ std::same_as<Expected> decltype (auto ) result = std::ranges:: fold_left (std::move (r2), init, f2);
219121 assert (result == expected);
220122 assert (telemetry.invocations == std::ranges::distance (r));
221123 assert (telemetry.moves == 0 );
@@ -231,37 +133,26 @@ constexpr void check(R r, T const& init, F f, Expected const& expected) {
231133 check_rvalue_range (r, init, f, expected);
232134}
233135
234- template <std::ranges::input_range R, class F , std::equality_comparable Expected>
235- requires std::copyable<R>
236- constexpr void check (R r, F f, std::optional<Expected> const & expected) {
237- check_iterator (r, f, expected);
238- }
239-
240136constexpr void empty_range_test_case () {
241137 auto const data = std::vector<int >{};
242138 check (data, 100 , std::plus (), 100 );
243139 check (data, -100 , std::multiplies (), -100 );
244- check (data, std::plus (), std::optional<int >());
245140
246141 check (data | std::views::take_while ([](auto ) { return false ; }), 1.23 , std::plus (), 1.23 );
247142 check (data, Integer (52 ), &Integer::plus, Integer (52 ));
248- check (data | std::views::take_while ([](auto ) { return false ; }), std::plus (), std::optional<int >());
249143}
250144
251145constexpr void common_range_test_case () {
252146 auto const data = std::vector<int >{1 , 2 , 3 , 4 };
253147 check (data, 0 , std::plus (), triangular_sum (data));
254148 check (data, 1 , std::multiplies (), factorial (data.back ()));
255- check (data, std::plus (), std::optional (triangular_sum (data)));
256- check (data, std::multiplies (), std::optional (factorial (data.back ())));
257149
258150 auto multiply_with_prev = [n = 1 ](auto const x, auto const y) mutable {
259151 auto const result = x * y * n;
260152 n = y;
261153 return static_cast <std::size_t >(result);
262154 };
263155 check (data, 1 , multiply_with_prev, factorial (data.size ()) * factorial (data.size () - 1 ));
264- check (data, multiply_with_prev, std::optional (factorial (data.size ()) * factorial (data.size () - 1 )));
265156
266157 auto fib = [n = 1 ](auto x, auto ) mutable {
267158 auto old_x = x;
@@ -293,7 +184,6 @@ constexpr void non_common_range_test_case() {
293184 auto data = std::vector<std::string>{" five" , " three" , " two" , " six" , " one" , " four" };
294185 auto range = data | std::views::transform (parse);
295186 check (range, 0 , std::plus (), triangular_sum (range));
296- check (range, std::plus (), std::optional (triangular_sum (range)));
297187 }
298188
299189 {
@@ -305,7 +195,6 @@ constexpr void non_common_range_test_case() {
305195 auto range =
306196 std::views::lazy_split (data, ' ' ) | std::views::transform (to_string_view) | std::views::transform (parse);
307197 check (range, 0 , std::plus (), triangular_sum (range));
308- check (range, std::plus (), std::optional (triangular_sum (range)));
309198 }
310199}
311200
@@ -327,32 +216,13 @@ void runtime_only_test_case() {
327216 {
328217 auto input = std::istringstream (raw_data);
329218 auto data = std::views::istream<std::string>(input);
330- is_in_value_result<std::ranges::basic_istream_view<std::string, char >, std::string> decltype (auto ) result =
331- fold_left_with_iter (data.begin (), data.end (), init, std::plus ());
332-
333- assert (result.in == data.end ());
334- assert (result.value == expected);
335- }
336-
337- {
338- auto input = std::istringstream (raw_data);
339- auto data = std::views::istream<std::string>(input);
340- is_in_value_result<std::ranges::basic_istream_view<std::string, char >, std::string> decltype (auto ) result =
341- fold_left_with_iter (data, init, std::plus ());
342- assert (result.in == data.end ());
343- assert (result.value == expected);
344- }
345-
346- {
347- auto input = std::istringstream (raw_data);
348- auto data = std::views::istream<std::string>(input);
349- assert (fold_left (data.begin (), data.end (), init, std::plus ()) == expected);
219+ assert (std::ranges::fold_left (data.begin (), data.end (), init, std::plus ()) == expected);
350220 }
351221
352222 {
353223 auto input = std::istringstream (raw_data);
354224 auto data = std::views::istream<std::string>(input);
355- assert (fold_left (data, init, std::plus ()) == expected);
225+ assert (std::ranges:: fold_left (data, init, std::plus ()) == expected);
356226 }
357227 }
358228#endif
0 commit comments