Horizon
Loading...
Searching...
No Matches
fold_left.hpp
Go to the documentation of this file.
1
2// Range v3 library
3//
4// Copyright Eric Niebler 2021-present
5//
6// Use, modification and distribution is subject to the
7// Boost Software License, Version 1.0. (See accompanying
8// file LICENSE_1_0.txt or copy at
9// http://www.boost.org/LICENSE_1_0.txt)
10//
11// Project home: https://github.com/ericniebler/range-v3
12
13#ifndef RANGES_V3_ALGORITHM_FOLD_LEFT_HPP
14#define RANGES_V3_ALGORITHM_FOLD_LEFT_HPP
15
16#include <meta/meta.hpp>
17
23
24#include <range/v3/detail/prologue.hpp>
25
26namespace ranges
27{
28 // clang-format off
31 template<class F, class T, class I, class U>
32 CPP_concept indirectly_binary_left_foldable_impl =
33 movable<T> &&
34 movable<U> &&
35 convertible_to<T, U> &&
36 invocable<F&, U, iter_reference_t<I>> &&
37 assignable_from<U&, invoke_result_t<F&, U, iter_reference_t<I>>>;
38
41 template<class F, class T, class I>
42 CPP_concept indirectly_binary_left_foldable =
43 copy_constructible<F> &&
44 indirectly_readable<I> &&
45 invocable<F&, T, iter_reference_t<I>> &&
46 convertible_to<invoke_result_t<F&, T, iter_reference_t<I>>,
47 std::decay_t<invoke_result_t<F&, T, iter_reference_t<I>>>> &&
48 indirectly_binary_left_foldable_impl<F, T, I, std::decay_t<invoke_result_t<F&, T, iter_reference_t<I>>>>;
49 // clang-format on
50
53 RANGES_FUNC_BEGIN(fold_left)
54
55 template(typename I, typename S, typename T, typename Op)(
56 requires sentinel_for<S, I> AND input_iterator<I> AND
57 indirectly_binary_left_foldable<Op, T, I>) //
58 constexpr auto
59 RANGES_FUNC(fold_left)(I first, S last, T init, Op op)
60 {
61 using U = std::decay_t<invoke_result_t<Op &, T, iter_reference_t<I>>>;
62
63 if(first == last)
64 {
65 return U(std::move(init));
66 }
67
68 U accum = invoke(op, std::move(init), *first);
69 for(++first; first != last; ++first)
70 {
71 accum = invoke(op, std::move(accum), *first);
72 }
73 return accum;
74 }
75
76 template(typename Rng, typename T, typename Op)(
77 requires input_range<Rng> AND
78 indirectly_binary_left_foldable<Op, T, iterator_t<Rng>>) //
79 constexpr auto
80 RANGES_FUNC(fold_left)(Rng && rng, T init, Op op)
81 {
82 return (*this)(begin(rng), end(rng), std::move(init), std::move(op));
83 }
84
85 RANGES_FUNC_END(fold_left)
86
87 RANGES_FUNC_BEGIN(fold_left_first)
88
89 template(typename I, typename S, typename Op)(
90 requires sentinel_for<S, I> AND input_iterator<I> AND
91 indirectly_binary_left_foldable<Op, iter_value_t<I>, I>
92 AND constructible_from<iter_value_t<I>, iter_reference_t<I>>) //
93 constexpr auto
94 RANGES_FUNC(fold_left_first)(I first, S last, Op op)
95 {
96 using U = invoke_result_t<fold_left_fn, I, S, iter_value_t<I>, Op>;
97 if(first == last)
98 {
99 return optional<U>();
100 }
101
102 iter_value_t<I> init = *first;
103 ++first;
104 return optional<U>(
105 in_place,
106 fold_left_fn{}(std::move(first), std::move(last), std::move(init), op));
107 }
108
109 template(typename R, typename Op)(
110 requires input_range<R> AND
111 indirectly_binary_left_foldable<Op, range_value_t<R>, iterator_t<R>>
112 AND constructible_from<range_value_t<R>, range_reference_t<R>>) //
113 constexpr auto
114 RANGES_FUNC(fold_left_first)(R && rng, Op op)
115 {
116 return (*this)(begin(rng), end(rng), std::move(op));
117 }
118
119 RANGES_FUNC_END(fold_left_first)
121} // namespace ranges
122
123#include <range/v3/detail/epilogue.hpp>
124
125#endif
typename Fn::template invoke< Args... > invoke
Evaluate the invocable Fn with the arguments Args.
Definition meta.hpp:541
front< Pair > first
Retrieve the first element of the pair Pair.
Definition meta.hpp:2251
Tiny meta-programming library.