VCCC  2024.05
VisualCamp Common C++ library
fold_left.hpp
Go to the documentation of this file.
1 //
2 // Created by yonggyulee on 1/26/24.
3 //
4 
5 #ifndef VCCC_ALGORITHM_RANGES_FOLD_LEFT_HPP
6 #define VCCC_ALGORITHM_RANGES_FOLD_LEFT_HPP
7 
8 #include <functional>
9 #include <type_traits>
10 #include <utility>
11 
22 #include "vccc/__ranges/begin.hpp"
23 #include "vccc/__ranges/end.hpp"
29 
30 namespace vccc {
31 namespace ranges {
32 namespace detail {
33 
34 template<typename F, typename T, typename I, typename U,
35  bool = conjunction<
36  movable<T>,
37  movable<U>,
38  convertible_to<T, U>,
39  invocable<F&, U, iter_reference_t<I>>
40  >::value /* true */>
41 struct indirectly_binary_left_foldable_impl
42  : assignable_from<U&, invoke_result_t<F&, U, iter_reference_t<I>>> {};
43 template<typename F, typename T, typename I, typename U>
44 struct indirectly_binary_left_foldable_impl<F, T, I, U, false> : std::false_type {};
45 
46 template<typename F, typename T, typename I,
47  bool = invocable<F&, T, iter_reference_t<I>>::value /* true */>
48 struct indirectly_binary_left_foldable_2
49  : conjunction<
50  convertible_to<
51  invoke_result_t<F&, T, iter_reference_t<I>>,
52  std::decay_t<invoke_result_t<F&, T, iter_reference_t<I>>>>,
53  indirectly_binary_left_foldable_impl<F, T, I, std::decay_t<invoke_result_t<F&, T, iter_reference_t<I>>>>
54  >{};
55 template<typename F, typename T, typename I>
56 struct indirectly_binary_left_foldable_2<F, T, I, false> : std::false_type {};
57 
58 template<typename F, typename T, typename I,
59  bool = conjunction<
60  copy_constructible<F>,
61  indirectly_readable<I>,
62  has_typename_type<iter_reference<I>>
63  >::value /* true */ >
64 struct indirectly_binary_left_foldable : indirectly_binary_left_foldable_2<F, T, I> {};
65 template<typename F, typename T, typename I>
66 struct indirectly_binary_left_foldable<F, T, I, false> : std::false_type {};
67 
68 struct fold_left_niebloid {
69  private:
71  struct check_range : std::false_type {};
72  template<typename R, typename T, typename F>
73  struct check_range<R, T, F, true>
74  : indirectly_binary_left_foldable<F, T, iterator_t<R>> {};
75 
76  public:
77  template<typename I, typename S, typename T, typename F, std::enable_if_t<conjunction<
78  input_iterator<I>,
79  sentinel_for<S, I>,
80  indirectly_binary_left_foldable<F, T, I>
81  >::value, int> = 0>
82  constexpr auto operator()(I first, S last, T init, F f) const {
83  using U = std::decay_t<invoke_result_t<F&, T, iter_reference_t<I>>>;
84 
85  if (first == last)
86  return U(std::move(init));
87 
88  U accum = vccc::invoke(f, std::move(init), *first);
89  for (++first; first != last; ++first) {
90  accum = vccc::invoke(f, std::move(accum), *first);
91  }
92 
93  return accum;
94  }
95 
97  constexpr auto operator()(R&& r, T init, F f) const {
98  return (*this)(ranges::begin(r), ranges::end(r), std::move(init), std::ref(f));
99  }
100 };
101 
102 } // namespace detail
103 
106 
107 VCCC_INLINE_OR_STATIC constexpr detail::fold_left_niebloid fold_left{};
108 
110 
111 } // namespace ranges
112 } // namespace vccc
113 
114 #endif // VCCC_ALGORITHM_RANGES_FOLD_LEFT_HPP
constexpr VCCC_INLINE_OR_STATIC detail::fold_left_niebloid fold_left
Definition: fold_left.hpp:107
constexpr invoke_result_t< F, Args... > invoke(F &&f, Args &&... args) noexcept(is_nothrow_invocable< F, Args... >::value)
Definition: invoke.hpp:38
constexpr VCCC_INLINE_OR_STATIC detail::begin_niebloid begin
returns an iterator to the beginning of a range
Definition: begin.hpp:116
constexpr VCCC_INLINE_OR_STATIC detail::end_niebloid end
returns a sentinel indicating the end of a range
Definition: end.hpp:120
#define VCCC_INLINE_OR_STATIC
Definition: inline_or_static.hpp:9
Definition: directory.h:12
constexpr VCCC_INLINE_OR_STATIC detail::element_niebloid< 0 > first
Definition: key_value.hpp:34
constexpr VCCC_INLINE_OR_STATIC detail::element_niebloid< 1 > value
Definition: key_value.hpp:35