GCC Code Coverage Report


Directory: include/kumi/
File: include/kumi/algorithm/fold.hpp
Date: 2026-10-14 16:33:56
Exec Total Coverage
Lines: 16 16 100.0%
Functions: 12 12 100.0%
Branches: 26 26 100.0%

Line Branch Exec Source
1 //======================================================================================================================
2 /*
3 KUMI - Compact Tuple Tools
4 Copyright : KUMI Project Contributors
5 SPDX-License-Identifier: BSL-1.0
6 */
7 //======================================================================================================================
8 #pragma once
9
10 namespace kumi
11 {
12 namespace _
13 {
14 template<typename F, typename T, typename V, std::size_t... I>
15 10 KUMI_HIDDEN_ABI constexpr auto fold_left_(kumi::_::adl_tag_t, F f, T&& t, V v, std::index_sequence<I...>)
16 {
17
10/10
✓ Branch 1 taken 4 times.
✓ Branch 4 taken 4 times.
✓ Branch 6 taken 2 times.
✓ Branch 7 taken 2 times.
✓ Branch 10 taken 6 times.
✓ Branch 14 taken 2 times.
✓ Branch 18 taken 2 times.
✓ Branch 22 taken 2 times.
✓ Branch 26 taken 2 times.
✓ Branch 30 taken 2 times.
158 return (kumi::function::foldable{v} >> ... >> kumi::bind_back(f, get<I>(KUMI_FWD(t))))();
18 6 }
19
20 template<typename F, typename T, typename V, std::size_t... I>
21 10 KUMI_HIDDEN_ABI constexpr auto fold_right_(kumi::_::adl_tag_t, F f, T&& t, V v, std::index_sequence<I...>)
22 {
23
8/8
✓ Branch 8 taken 2 times.
✓ Branch 11 taken 2 times.
✓ Branch 14 taken 2 times.
✓ Branch 17 taken 2 times.
✓ Branch 20 taken 2 times.
✓ Branch 23 taken 2 times.
✓ Branch 26 taken 2 times.
✓ Branch 29 taken 2 times.
148 return (kumi::bind_front(f, get<I>(KUMI_FWD(t))) << ... << kumi::function::foldable{v})();
24 6 }
25 }
26
27 struct fold_left_t
28 {
29 template<typename Function, kumi::concepts::product_type T, typename Value>
30 [[nodiscard]] KUMI_ABI constexpr auto operator()(Function f, T&& t, Value init) const
31 {
32
1/1
✓ Branch 1 taken 2 times.
4 if constexpr (kumi::concepts::record_type<T>) return (*this)(f, kumi::values_of(KUMI_FWD(t)), init);
33 else if constexpr (kumi::concepts::empty_product_type<T>) return init;
34
2/2
✓ Branch 1 taken 4 times.
✓ Branch 4 taken 4 times.
4 else return fold_left_(kumi::_::adl_tag, f, KUMI_FWD(t), init, kumi::function::indexes_for<T>{});
35 }
36
37 template<typename Function, kumi::concepts::non_empty_product_type T>
38 [[nodiscard]] KUMI_ABI constexpr auto operator()(Function f, T&& t) const
39 {
40 1 if constexpr (kumi::concepts::record_type<T>) return (*this)(f, kumi::values_of(KUMI_FWD(t)));
41 else if constexpr (kumi::concepts::sized_product_type<T, 1>) return get<0>(KUMI_FWD(t));
42 else
43
1/1
✓ Branch 1 taken 2 times.
2 return fold_left_(kumi::_::adl_tag, f, KUMI_FWD(t), get<0>(KUMI_FWD(t)),
44 2 kumi::function::shift_index_sequence<1, kumi::size_v<T> - 1>{});
45 }
46 };
47
48 struct fold_right_t
49 {
50 template<typename Function, kumi::concepts::product_type T, typename Value>
51 [[nodiscard]] KUMI_ABI constexpr auto operator()(Function f, T&& t, Value init) const
52 {
53
1/1
✓ Branch 1 taken 2 times.
4 if constexpr (kumi::concepts::record_type<T>) return (*this)(f, kumi::values_of(KUMI_FWD(t)), init);
54 else if constexpr (kumi::concepts::empty_product_type<T>) return init;
55
2/2
✓ Branch 1 taken 4 times.
✓ Branch 4 taken 4 times.
4 else return fold_right_(kumi::_::adl_tag, f, KUMI_FWD(t), init, kumi::function::indexes_for<T>{});
56 }
57
58 template<typename Function, kumi::concepts::non_empty_product_type T>
59 [[nodiscard]] KUMI_ABI constexpr auto operator()(Function f, T&& t) const
60 {
61 1 if constexpr (kumi::concepts::record_type<T>) return (*this)(f, kumi::values_of(KUMI_FWD(t)));
62 else if constexpr (kumi::concepts::sized_product_type<T, 1>) return get<0>(KUMI_FWD(t));
63 else
64
1/1
✓ Branch 1 taken 2 times.
2 return fold_right_(kumi::_::adl_tag, f, KUMI_FWD(t), get<0>(KUMI_FWD(t)),
65 2 kumi::function::shift_index_sequence<1, kumi::size_v<T> - 1>{});
66 }
67 };
68
69 //====================================================================================================================
70 /**
71 @ingroup kumi_reductions
72
73 @var fold_left
74 @brief Callable object computing the generalized combination of all elements using a tail recursive call.
75
76 On record types, this function operates on the underlying values, not on the fields themselves.
77
78 @qualifier nodiscard
79 @qualifier inline
80 @qualifier constexpr
81
82 @groupheader{Header file}
83 @code
84 #include <kumi/algorithm/fold.hpp>
85 @endcode
86
87 @groupheader{Call Signature}
88
89 @code
90 template<typename Function, product_type T, typename Value>
91 constexpr auto fold_left(Function && f, T && t, Value init);
92 @endcode
93
94 @code
95 template<typename Function, product_type T>
96 constexpr auto fold_left(Function && f, T && t);
97 @endcode
98
99 @subgroupheader{Parameters}
100
101 - `f`: Binary callable function to apply
102 - `t`: Product type to operate on
103 - `init`: Optional initial value of the fold, first element is used otherwise
104
105 @subgroupheader{Return value}
106
107 - The resulting value of the application of the function `f( f( f(init, get<0>(t)), ...), get<N-1>(t))`
108
109 @groupheader{Helper type}
110
111 @snippet include/kumi/algorithm/fold.hpp fold_left_t
112
113 Computes the return type of a call to kumi::fold_left
114
115 @groupheader{Examples}
116
117 @tab_begin
118
119 @tab{Tuple}
120 @godbolt{doc/tuple/algo/fold_left.cpp}
121
122 @tab{Record}
123 @godbolt{doc/record/algo/fold_left.cpp}
124
125 @tab_end
126 **/
127 //====================================================================================================================
128 KUMI_VARIABLE_ABI constexpr fold_left_t fold_left{};
129
130 //====================================================================================================================
131 /**
132 @ingroup kumi_reductions
133
134 @var fold_right
135 @brief Callable object computing the generalized combination of all elements using a non-tail recursive call.
136
137 On record types, this function operates on the underlying values, not on the fields themselves.
138
139 @qualifier nodiscard
140 @qualifier inline
141 @qualifier constexpr
142
143 @groupheader{Header file}
144 @code
145 #include <kumi/algorithm/fold.hpp>
146 @endcode
147
148 @groupheader{Call Signature}
149
150 @code
151 template<typename Function, product_type T, typename Value>
152 constexpr auto fold_right(Function && f, T && t, Value init);
153 @endcode
154
155 @code
156 template<typename Function, product_type T>
157 constexpr auto fold_right(Function && f, T && t);
158 @endcode
159
160 @subgroupheader{Parameters}
161
162 - `f`: Binary callable function to apply
163 - `t`: Product type to operate on
164 - `init`: Optional initial value of the fold, last element is used otherwise
165
166 @subgroupheader{Return value}
167
168 - The resulting value of the application of the function `f(get<0>(t), f(... , f(get<N-1>(t), init))`
169
170 @groupheader{Helper type}
171
172 @snippet include/kumi/algorithm/fold.hpp fold_right_t
173
174 Computes the return type of a call to kumi::fold_right
175
176 @groupheader{Examples}
177
178 @tab_begin
179
180 @tab{Tuple}
181 @godbolt{doc/tuple/algo/fold_right.cpp}
182
183 @tab{Record}
184 @godbolt{doc/record/algo/fold_right.cpp}
185
186 @tab_end
187 **/
188 //====================================================================================================================
189 KUMI_VARIABLE_ABI constexpr fold_right_t fold_right{};
190
191 namespace result
192 {
193 //! [fold_left_t]
194 template<typename Function, kumi::concepts::product_type T, typename... Value>
195 requires((sizeof...(Value) == 0) || (sizeof...(Value) == 1))
196 using fold_left_t =
197 decltype(kumi::fold_left(std::declval<Function>(), std::declval<T>(), std::declval<Value>()...));
198
199 template<typename Function, kumi::concepts::product_type T, typename... Value>
200 requires((sizeof...(Value) == 0) || (sizeof...(Value) == 1))
201 struct fold_left
202 {
203 using type = kumi::result::fold_left_t<Function, T, Value...>;
204 };
205
206 //! [fold_left_t]
207
208 //! [fold_right_t]
209 template<typename Function, kumi::concepts::product_type T, typename... Value>
210 requires((sizeof...(Value) == 0) || (sizeof...(Value) == 1))
211 using fold_right_t =
212 decltype(kumi::fold_right(std::declval<Function>(), std::declval<T>(), std::declval<Value>()...));
213
214 template<typename Function, kumi::concepts::product_type T, typename... Value>
215 requires((sizeof...(Value) == 0) || (sizeof...(Value) == 1))
216 struct fold_right
217 {
218 using type = kumi::result::fold_right_t<Function, T, Value...>;
219 };
220
221 //! [fold_right_t]
222 }
223 }
224