GCC Code Coverage Report


Directory: include/kumi/
File: include/kumi/utils/field.hpp
Date: 2026-10-14 16:33:56
Exec Total Coverage
Lines: 22 22 100.0%
Functions: 553 581 95.2%
Branches: 0 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 //====================================================================================================================
13 /**
14 @ingroup kumi_types
15 @class field
16 @brief Named wrapper over a type.
17
18 kumi::field provides a way to define named fields in a product type. Any type can be used as an identifier as long
19 as it models kumi::concepts::identifier.
20
21 @tparam Id a compile time string that is used to retrieve the field.
22 @tparam T the type of the value that is wrapped.
23 **/
24 //====================================================================================================================
25 template<typename Id, typename T> struct field
26 {
27 /// Name associated to the field
28 static constexpr auto label() { return kumi::_::make_str(Id{}); }
29
30 using type = T;
31 using identifier_type = Id;
32 using inner_type = std::type_identity<T>;
33 using label_type = std::integral_constant<kumi::str<label().size()>, label()>;
34
35 T value;
36
37 2112 KUMI_HIDDEN_ABI constexpr T& operator()(identifier_type) & noexcept { return value; }
38
39 789 KUMI_HIDDEN_ABI constexpr T&& operator()(identifier_type) && noexcept { return static_cast<T&&>(value); }
40
41 2960 KUMI_HIDDEN_ABI constexpr T const& operator()(identifier_type) const& noexcept { return value; }
42
43 8 KUMI_HIDDEN_ABI constexpr T const&& operator()(identifier_type) const&& noexcept
44 {
45 8 return static_cast<T const&&>(value);
46 }
47
48 20 KUMI_HIDDEN_ABI constexpr T& operator()(inner_type) & noexcept { return value; }
49
50 KUMI_HIDDEN_ABI constexpr T&& operator()(inner_type) && noexcept { return static_cast<T&&>(value); }
51
52 6 KUMI_HIDDEN_ABI constexpr T const& operator()(inner_type) const& noexcept { return value; }
53
54 KUMI_HIDDEN_ABI constexpr T const&& operator()(inner_type) const&& noexcept
55 {
56 return static_cast<T const&&>(value);
57 }
58
59 70 KUMI_HIDDEN_ABI constexpr T& operator()(label_type) & noexcept { return value; }
60
61 KUMI_HIDDEN_ABI constexpr T&& operator()(label_type) && noexcept { return static_cast<T&&>(value); }
62
63 6 KUMI_HIDDEN_ABI constexpr T const& operator()(label_type) const& noexcept { return value; }
64
65 KUMI_HIDDEN_ABI constexpr T const&& operator()(label_type) const&& noexcept
66 {
67 return static_cast<T const&&>(value);
68 }
69
70 //==================================================================================================================
71 /// @ingroup kumi_utility
72 //! @related kumi::field
73 //! @brief Inserts a kumi::field in an output stream
74 //==================================================================================================================
75 template<typename CharT, typename Traits>
76 1138 friend std::basic_ostream<CharT, Traits>& operator<<(std::basic_ostream<CharT, Traits>& os, field const& w) noexcept
77 {
78 1138 return os << kumi::_::make_str(std::remove_cvref_t<Id>{}) << " : " << kumi::_::make_streamable(w.value);
79 }
80 };
81
82 // EBO
83 template<typename Id, typename T>
84 requires(std::is_empty_v<T> && !std::is_final_v<T>)
85 struct field<Id, T> : T
86 {
87 /// Name associated to the field
88 static constexpr auto label() { return kumi::_::make_str(Id{}); }
89
90 using type = T;
91 using identifier_type = Id;
92 using inner_type = std::type_identity<T>;
93 using label_type = std::integral_constant<kumi::str<label().size()>, label()>;
94
95 32 KUMI_HIDDEN_ABI constexpr T& operator()(identifier_type) & noexcept { return *this; }
96
97 16 KUMI_HIDDEN_ABI constexpr T&& operator()(identifier_type) && noexcept { return static_cast<T&&>(*this); }
98
99 69 KUMI_HIDDEN_ABI constexpr T const& operator()(identifier_type) const& noexcept { return *this; }
100
101 KUMI_HIDDEN_ABI constexpr T const&& operator()(identifier_type) const&& noexcept
102 {
103 return static_cast<T const&&>(*this);
104 }
105
106 KUMI_HIDDEN_ABI constexpr T& operator()(inner_type) & noexcept { return *this; }
107
108 KUMI_HIDDEN_ABI constexpr T&& operator()(inner_type) && noexcept { return static_cast<T&&>(*this); }
109
110 KUMI_HIDDEN_ABI constexpr T const& operator()(inner_type) const& noexcept { return *this; }
111
112 KUMI_HIDDEN_ABI constexpr T const&& operator()(inner_type) const&& noexcept
113 {
114 return static_cast<T const&&>(*this);
115 }
116
117 KUMI_HIDDEN_ABI constexpr T& operator()(label_type) & noexcept { return *this; }
118
119 KUMI_HIDDEN_ABI constexpr T&& operator()(label_type) && noexcept { return static_cast<T&&>(*this); }
120
121 KUMI_HIDDEN_ABI constexpr T const& operator()(label_type) const& noexcept { return *this; }
122
123 KUMI_HIDDEN_ABI constexpr T const&& operator()(label_type) const&& noexcept
124 {
125 return static_cast<T const&&>(*this);
126 }
127
128 //==================================================================================================================
129 /// @ingroup kumi_utility
130 //! @related kumi::field
131 //! @brief Inserts a kumi::field in an output stream
132 //==================================================================================================================
133 template<typename CharT, typename Traits>
134 1 friend std::basic_ostream<CharT, Traits>& operator<<(std::basic_ostream<CharT, Traits>& os, field const& w) noexcept
135 {
136 1 return os << kumi::_::make_str(std::remove_cvref_t<Id>{}) << " : "
137 1 << kumi::_::make_streamable(w(_::identifier_of_t<decltype(w)>{}));
138 }
139 };
140
141 /// Specialisation to clearly indicate an error
142 template<typename Id, typename T>
143 requires(!kumi::_::valid_label<Id>)
144 struct field<Id, T>
145 {
146 field(T&&) = delete;
147 static_assert(kumi::_::valid_label<Id>, "User defined to_str(...) function is not constexpr");
148 };
149
150 //====================================================================================================================
151 /**
152 @ingroup kumi_utility
153 @brief Extracts the identifiers from a kumi::concepts::field or returns the parameter.
154
155 @note If the unqualified type of input does not model kumi::concepts::field, returns kumi::unknown.
156 @tparam T The type to extract the identifier from.
157 @return The identifier of the field or kumi::unknown.
158
159 ## Helper type
160 @code
161 namespace kumi::result
162 {
163 template<typename Ts> struct identifier_of;
164
165 template<typename T> using identifier_of_t = typename identifier_of<T>::type;
166 }
167 @endcode
168
169 Computes the return type of a call to kumi::identifier_of
170
171 ## Example:
172 @include doc/infra/identifier_of.cpp
173 **/
174 //====================================================================================================================
175 template<typename T> [[nodiscard]] KUMI_ABI consteval auto identifier_of() noexcept
176 {
177 if constexpr (kumi::_::field<T>) return kumi::_::identifier_of_t<T>{};
178 else return kumi::unknown{};
179 }
180
181 //====================================================================================================================
182 /**
183 @ingroup kumi_utility
184 @brief Extracts the label from a kumi::concepts::field or returns the parameter.
185
186 @note If the unqualified type of input does not model kumi::concepts::field, returns kumi::unknown.
187 @tparam T The type to extract label from.
188 @return The label of the field as a kumi::str.
189
190 ## Helper type
191 @code
192 namespace kumi::result
193 {
194 template<typename Ts> struct label_of;
195
196 template<typename T> using label_of_t = typename label_of<T>::type;
197 }
198 @endcode
199
200 Computes the return type of a call to kumi::label_of
201
202 ## Example:
203 @include doc/infra/label_of.cpp
204 **/
205 //====================================================================================================================
206 template<typename T> [[nodiscard]] KUMI_ABI consteval kumi::_::str_like auto label_of() noexcept
207 {
208 if constexpr (kumi::_::field<T>) return kumi::_::label_of_t<T>::value;
209 else return kumi::unknown::value;
210 }
211
212 //====================================================================================================================
213 /**
214 @ingroup kumi_utility
215 @brief Extracts the value from a kumi::concepts::field or returns the parameter
216
217 @note If the unqualified type of input does not model kumi::concepts::field, simply forwards the parameter
218 @tparam T The type to extract the value from.
219 @param t A forwarding reference to the input object.
220 @return A forwarded value of the unwrapped object.
221
222 ## Helper type
223 @code
224 namespace kumi::result
225 {
226 template<typename Ts> struct field_value_of;
227
228 template<typename T> using field_value_of_t = typename field_value_of<T>::type;
229 }
230 @endcode
231
232 Computes the return type of a call to kumi::field_value_of
233
234 ## Example:
235 @include doc/infra/field_value_of.cpp
236 **/
237 //====================================================================================================================
238 template<typename T> [[nodiscard]] KUMI_ABI constexpr decltype(auto) field_value_of(T&& t) noexcept
239 {
240 1413 if constexpr (kumi::_::field<T>) return (KUMI_FWD(t)(kumi::_::identifier_of_t<T>{}));
241 3 else return KUMI_FWD(t);
242 }
243
244 //====================================================================================================================
245 /**
246 @ingroup kumi_utility
247 @brief Creates a field from a given value keeping the qualifiers.
248
249 @tparam Name The label to associate to the field.
250 @param t A forwarding reference to the input object.
251 @return A `field` that correctly keeps the qualified input type.
252 @related kumi::field
253
254 ## Helper type
255 @code
256 namespace kumi::result
257 {
258 template<typename Ts> struct capture_field;
259
260 template<typename T> using capture_field_t = typename capture_field<T>::type;
261 }
262 @endcode
263
264 Computes the return type of a call to kumi::capture_field
265
266 ## Example:
267 @include doc/infra/capture_field.cpp
268 **/
269 //====================================================================================================================
270 template<_::identifier auto Name, typename T>
271 [[nodiscard]] KUMI_ABI constexpr decltype(auto) capture_field(T&& t) noexcept
272 {
273 320 return kumi::field<decltype(Name), T>{KUMI_FWD(t)};
274 }
275
276 //====================================================================================================================
277 /**
278 @ingroup kumi_utility
279 @brief Casts the provided value to the target type using `static_cast`.
280
281 @note If the type to convert models kumi::concepts::field, the function does not rename the input parameter.
282
283 @tparam U The type to convert the parameter to.
284 @param t A forwarding reference to the input object.
285 @return A value of type U.
286 @related kumi::field
287
288 ## Helper type
289 @code
290 namespace kumi::result
291 {
292 template<typename Ts> struct field_cast;
293
294 template<typename T> using field_cast_t = typename field_cast<T>::type;
295 }
296 @endcode
297
298 Computes the return type of a call to kumi::field_cast
299
300 ## Example:
301 @include doc/infra/field_cast.cpp
302 **/
303 //====================================================================================================================
304 template<typename U, typename T> [[nodiscard]] KUMI_ABI constexpr decltype(auto) field_cast(T&& t) noexcept
305 {
306 if constexpr (kumi::_::field<U>)
307 return kumi::field<kumi::_::identifier_of_t<T>, kumi::_::type_of_t<U>>{
308 1 static_cast<kumi::_::type_of_t<U>>(KUMI_FWD(t)(kumi::_::identifier_of_t<T>{}))};
309 else if constexpr (!kumi::_::field<T>) return static_cast<kumi::_::type_of_t<U>>(KUMI_FWD(t));
310 29 else return kumi::field<kumi::_::identifier_of_t<T>, U>{static_cast<U>(KUMI_FWD(t)(kumi::_::identifier_of_t<T>{}))};
311 }
312
313 namespace result
314 {
315 template<typename T> using identifier_of_t = decltype(kumi::identifier_of<T>());
316
317 template<typename T> struct identifier_of
318 {
319 using type = kumi::result::identifier_of_t<T>;
320 };
321
322 template<typename T> using label_of_t = decltype(kumi::label_of<T>());
323
324 template<typename T> struct label_of
325 {
326 using type = kumi::result::label_of_t<T>;
327 };
328
329 template<typename T> using field_value_of_t = decltype(kumi::field_value_of(std::declval<T>()));
330
331 template<typename T> struct field_value_of
332 {
333 using type = kumi::result::field_value_of_t<T>;
334 };
335
336 template<_::identifier auto Name, typename T>
337 using capture_field_t = decltype(kumi::capture_field<Name>(std::declval<T>()));
338
339 template<kumi::_::identifier auto Name, typename T> struct capture_field
340 {
341 using type = kumi::result::capture_field_t<Name, T>;
342 };
343
344 template<typename U, typename T> using field_cast_t = decltype(kumi::field_cast<U, T>(std::declval<T>()));
345
346 template<typename U, typename T> struct field_cast
347 {
348 using type = kumi::result::field_cast_t<U, T>;
349 };
350 }
351 }
352