GCC Code Coverage Report


Directory: include/kumi/
File: include/kumi/functional/monadic.hpp
Date: 2026-10-14 16:33:56
Exec Total Coverage
Lines: 10 10 100.0%
Functions: 0 0 -%
Branches: 24 24 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::function
11 {
12 //====================================================================================================================
13 /**
14 @ingroup kumi_functional
15 @brief If T is a kumi::product_type, returns its number of elements otherwise returns V;
16
17 @tparam T type to inspect
18 @tparam V fallback value
19
20 ## Helper value
21 @code
22 template<typename T, auto V> inline constexpr std::size_t size_or_v = size_or<T,V>::value;
23 @endcode
24 **/
25 //====================================================================================================================
26 template<typename T, auto V> inline constexpr auto size_or_v = V;
27
28 template<typename T, auto V>
29 requires(kumi::concepts::product_type<T>)
30 inline constexpr auto size_or_v<T, V> = kumi::size_v<T>;
31
32 template<typename T, auto V> struct size_or
33 {
34 static constexpr auto value = kumi::function::size_or_v<T, V>;
35 };
36
37 //====================================================================================================================
38 /**
39 @ingroup kumi_functional
40 @brief Returns the Ith element of `t` if `t` is a kumi::product_type, an instance of `v` otherwise.
41
42 @note Does not participate in overload resolution if `I` is out of [0, kumi::size_v<T>).
43 @tparam I Compile-time index of the element to access
44 @param t Type to inspect
45 @param v Fallback value
46 @return A reference to the selected element of `t` if `t` is a kumi::product_type, the parameter `v` otherwise.
47 **/
48 //====================================================================================================================
49 template<std::size_t I, typename T, typename V> [[nodiscard]] KUMI_ABI constexpr decltype(auto) get_or(T&& t, V&& v)
50 {
51 33 if constexpr (kumi::concepts::product_type<T> && I < kumi::size_v<T>) return get<I>(KUMI_FWD(t));
52 9 else return KUMI_FWD(v);
53 }
54
55 //====================================================================================================================
56 /**
57 @ingroup kumi_functional
58 @brief Computes the Ith element type of a kumi::product_type, or a fallback type `U` otherwise.
59
60 If `T` is a kumi::product_type and `I` is within its size, this alias resolves to `element_t<I,T>`, otherwise it
61 resolves to `U`.
62
63 @tparam I Index of the element type to retrieve
64 @tparam T Type to access
65 @tparam U Fallback type
66
67 ## Helper type
68 @code
69 namespace kumi
70 {
71 template<std::size_t I, typename T, typename U> using element_or_t = typename element_or<I,T,U>::type;
72 }
73 @endcode
74 **/
75 //====================================================================================================================
76 template<std::size_t I, typename T, typename U>
77 using element_or_t = std::remove_cvref_t<decltype(kumi::function::get_or<I>(std::declval<T>(), std::declval<U>()))>;
78
79 template<std::size_t I, typename T, typename U> struct element_or
80 {
81 using type = kumi::function::element_or_t<I, T, U>;
82 };
83
84 //====================================================================================================================
85 /**
86 @class foldable
87 @ingroup kumi_functional
88 @brief Functional wrapper for values to facilitate pipelined transformations.
89
90 kumi::function::foldable provides a lightweight wrapper that enables functional-style chaining of operations
91 using the `>>` and `<<` operators. It acts as an identity functor, allowing a value to be
92 transformed through a sequence of callables without manual temporary variables.
93
94 @tparam T Type of the value stored inside kumi::foldable.
95 **/
96 //====================================================================================================================
97 template<typename T> struct foldable
98 {
99 T value;
100
101 //==================================================================================================================
102 /**
103 @brief Pipelines the value contained in the foldable into a unary callable, chaining computation from left
104 to right.
105
106 @param f The foldable instance.
107 @param c The unary callable
108 @return A new kumi::foldable containing the result of the invocation.
109 **/
110 //==================================================================================================================
111 template<typename C> KUMI_ABI friend constexpr decltype(auto) operator>>(foldable&& f, C&& c)
112 {
113
12/12
✓ Branch 1 taken 4 times.
✓ Branch 4 taken 4 times.
✓ Branch 7 taken 4 times.
✓ Branch 10 taken 4 times.
✓ Branch 13 taken 2 times.
✓ Branch 16 taken 2 times.
✓ Branch 19 taken 2 times.
✓ Branch 22 taken 2 times.
✓ Branch 25 taken 2 times.
✓ Branch 28 taken 2 times.
✓ Branch 31 taken 2 times.
✓ Branch 34 taken 2 times.
538 return kumi::function::foldable{kumi::invoke(c, f.value)};
114 }
115
116 //==================================================================================================================
117 /**
118 @brief Pipelines the value contained in the foldable into a unary callable, chaining computation from right
119 to left.
120
121 @param f The foldable instance.
122 @param c The unary callable
123 @return A new kumi::foldable containing the result of the invocation.
124 **/
125 //==================================================================================================================
126 template<typename C> KUMI_ABI friend constexpr decltype(auto) operator<<(C&& c, foldable&& f)
127 {
128
12/12
✓ Branch 1 taken 4 times.
✓ Branch 4 taken 4 times.
✓ Branch 7 taken 4 times.
✓ Branch 10 taken 4 times.
✓ Branch 13 taken 2 times.
✓ Branch 16 taken 2 times.
✓ Branch 19 taken 2 times.
✓ Branch 22 taken 2 times.
✓ Branch 25 taken 2 times.
✓ Branch 28 taken 2 times.
✓ Branch 31 taken 2 times.
✓ Branch 34 taken 2 times.
38 return kumi::function::foldable{kumi::invoke(c, f.value)};
129 }
130
131 //==================================================================================================================
132 /**
133 @brief Finalizes the fold.
134 @return The value contained in a foldable, essentially marking the end of a computation.
135 **/
136 //==================================================================================================================
137 86 KUMI_ABI constexpr auto operator()() const noexcept { return value; }
138 };
139
140 //====================================================================================================================
141 /**
142 @class scannable
143 @ingroup kumi_functional
144 @brief Functional wrapper that accumulates state during a transformation chain.
145
146 kumi::scannable tracks both a current value and a transformation history. As the value is
147 piped through callables, the previous state is bound into the underlying function,
148 effectively performing a "scan" or "prefix sum" at the type level.
149
150 @tparam F The accumulated function state (partial applications).
151 @tparam V The current result value.
152 **/
153 //====================================================================================================================
154 template<typename F, typename V> struct scannable
155 {
156 F func;
157 V value;
158
159 //==================================================================================================================
160 /**
161 @brief Pipelines the current value into a unary callable and accumulates the operation into the function state,
162 chaining computations from left to right.
163
164 @param s The scannable instance.
165 @param c The callable to apply.
166 @return A new kumi::scannable with updated value and bound function state.
167 **/
168 //==================================================================================================================
169 template<typename C> KUMI_ABI friend constexpr decltype(auto) operator>>(scannable&& s, C&& c)
170 {
171 68 auto res = kumi::invoke(c, s.value);
172 272 return kumi::function::scannable{kumi::bind_front(std::move(s.func), std::move(s.value)), res};
173 }
174
175 //==================================================================================================================
176 /**
177 @brief Pipelines the current value into a unary callable and accumulates the operation into the function state,
178 chaining computations from right to left.
179
180 @param c The callable to apply.
181 @param s The scannable instance.
182 @return A new kumi::scannable with updated value and bound function state.
183 **/
184 //==================================================================================================================
185 template<typename C> KUMI_ABI friend constexpr decltype(auto) operator<<(C&& c, scannable&& s)
186 {
187 68 auto res = kumi::invoke(c, s.value);
188 272 return kumi::function::scannable{kumi::bind_back(std::move(s.func), std::move(s.value)), res};
189 }
190
191 //==================================================================================================================
192 /**
193 @brief Finalizes the scan.
194 @return The invocation of the bounded function with the last value contained in a scannable.
195 Essentially marking the end of a computation.
196 **/
197 //==================================================================================================================
198 64 KUMI_ABI constexpr decltype(auto) operator()() const noexcept { return kumi::invoke(func, value); }
199 };
200
201 //====================================================================================================================
202 /**
203 @related kumi::function::foldable
204 @brief kumi::function::foldable deduction guide
205 @tparam T Type to wrap into the foldable context.
206 **/
207 //====================================================================================================================
208 template<typename T> foldable(T&& t) -> foldable<std::unwrap_ref_decay_t<T>>;
209
210 //====================================================================================================================
211 /**
212 @related kumi::function::scannable
213 @brief kumi::function::scannable deduction guide
214 @tparam T Type to wrap into the foldable context.
215 @tparam F Function to bind arguments to in order to build the history.
216 **/
217 //====================================================================================================================
218 template<typename F, typename T> scannable(F&& f, T&& t) -> scannable<F, std::unwrap_ref_decay_t<T>>;
219 }
220