| 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 |