Horizon
fold_left.hpp
Go to the documentation of this file.
1 // 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 
26 namespace ranges
27 {
28  // clang-format off
31  template<class F, class T, class I, class U>
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>
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
CPP_concept indirectly_binary_left_foldable
\concept indirectly_binary_left_foldable
Definition: fold_left.hpp:42
CPP_concept indirectly_binary_left_foldable_impl
\concept indirectly_binary_left_foldable_impl
Definition: fold_left.hpp:32
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.