ALib C++ Library
Library Version: 2402 R1
Documentation generated by doxygen
Loading...
Searching...
No Matches
typetraits.inl
Go to the documentation of this file.
1/** ************************************************************************************************
2 * \file
3 * This header file is part of module \alib_boxing of the \aliblong.
4 *
5 * \emoji :copyright: 2013-2024 A-Worx GmbH, Germany.
6 * Published under \ref mainpage_license "Boost Software License".
7 **************************************************************************************************/
8#ifndef HPP_ALIB_BOXING_TYPETRAITS
9#define HPP_ALIB_BOXING_TYPETRAITS 1
10
11#if !defined(HPP_ALIB_BOXING_BOXING)
12# error "ALib sources with ending '.inl' must not be included from outside."
13#endif
14
15namespace alib { namespace boxing {
16
17namespace detail {
18/**
19 * This type is used internally with struct \alib{boxing;TMappedTo}.
20 *
21 * \note
22 * The type is not used by user code. However, working with a debugger, when investigating
23 * to the \alib{boxing::detail;VTable} of a box value, this type will nicely denote that
24 * the mapped type is not an array.
25 */
26struct TPlain {};
27
28/**
29 * This type is used internally with struct \alib{boxing;TMappedToArrayOf}.
30 *
31 * \note
32 * The type is not used by user code. However, working with a debugger, when investigating
33 * to the \alib{boxing::detail;VTable} of a box value, this type will nicely denote that
34 * the mapped type is an array.
35 */
36struct TArrayOf {};
37
38/**
39 * This is an empty type used to denote that default boxing is active. The type is
40 * used with the default implementation of TMP struct \alib{boxing;T_Boxer}.
41 * Providing this type in custom specializations (wrapped in \alib{boxing;TMappedTo}),
42 * make such specialization in-effective.
43 *
44 * \see
45 * Templated struct \alib{boxing;T_Boxer} for more information.
46 */
48
49
50/**
51 * This is an empty type used to denote that a type must not be boxed.
52 * To disable \alib_boxing_nl for a custom type, a specialization of type traits
53 * struct \alib{boxing;T_Boxer} must use this type (wrapped in \alib{boxing;TMappedTo}), to
54 * define type member \alib{boxing;T_Boxer::Mapping}.
55 *
56 * \see
57 * Templated struct \alib{boxing;T_Boxer} for more information.
58 */
59struct TNotBoxable {};
60
61}
62
63/**
64 * This type is used with to denote type mapping with standard, non-array types.
65 *
66 * Type mappings using either this or sibling struct \alib{boxing;TMappedToArrayOf}, have
67 * to be provided with
68 * - Specializations of \alib{boxing;T_Boxer}, and
69 * - Namespace function \alib{boxing;BootstrapRegister} used to associated box-function implementations
70 * with mapped types.
71 *
72 * \see
73 * Templated struct \alib{boxing;T_Boxer} for more information.
74 *
75 * @tparam TMapped The boxed type.
76 */
77template<typename TMapped>
79{
80 /**
81 * The given type \p{TMapped}.<br>
82 */
83 using Type = TMapped;
84
85 /**
86 * Denotes that the type is not boxed to an array type.
87 */
89
90};
91
92
93/**
94 * This type is used to define type mappings targeting array-types.
95 * Array types consist of a an element type as well as a length.
96 * Corresponding specializations of \alib{boxing;T_Boxer::Write} and \alib{boxing;T_Boxer::Read}
97 * have to use write the pointer to the start of the array and the array's length into
98 * the box's \alib{boxing;Placeholder}.
99 *
100 * \see
101 * Sibling struct \alib{boxing;TMappedTo} used to denote mapping to standard non-array types.
102 *
103 * @tparam TElement The boxed array's element type.
104 */
105template<typename TElement>
107{
108 /**
109 * The element type given as \p{TElement}.<br>
110 */
111 using Type = TElement;
112
113 /**
114 * Denotes that the type is boxed to an array type.
115 */
117};
118
119/** ************************************************************************************************
120 * This template struct is used to define customized behavior for boxing C++ type
121 * \p{TBoxable}.
122 *
123 * ### Default Boxing: ###
124 * If this struct is \b not specialized for template type \p{TBoxable},
125 * default boxing applies.
126 * With that, values \b and pointers of a type are boxed in the same way:
127 * - They are both boxed to a pointer of \p{TBoxable} if a value of the type does not "fit" into
128 * a box's \alib{boxing;Placeholder} or if the type is not copy-constructible or not
129 * trivially destructible.
130 * - Otherwise, both are boxed as values, hence if a pointer is given to the constructor or
131 * assign \c operator= of class \alib{boxing;Box}, indirection \c operator* is applied.
132 *
133 * <br><p>
134 * ###Custom Boxing With Specializations Of This Struct: ###
135 * The default boxing briefly described above, can be manipulated by providing a specialization
136 * of this struct.
137 * All three entities of this default implementation have to be provided with such specializations:
138 *
139 * 1. <b>Type definition #Mapping:</b><br>
140 * The mapped type must be given using helper struct \alib{boxing;TMappedTo} or
141 * \alib{boxing;TMappedToArrayOf}. The mapped type needs to be given as an explicit template
142 * parameter of those.
143 * In the case of TMappedTo, the template parameter denotes the mapped type, while
144 * with TMappedToArrayOf, the template parameter denotes the type of the elements of the boxed
145 * C++ array.
146 *
147 * If special type \alib{boxing;detail::TNotBoxable} is given (still wrapped in the helper, hence given
148 * as <c>TMappedTo<TNotBoxable></c>), then boxing is disallowed for type \p{TBoxed}.
149 * In this case, only declarations of functions #Write and #Read need to be provided, as they
150 * are never invoked.
151 *
152 * The default implementation of this struct uses a second special type available,
153 * \alib{boxing;detail::TDefaultBoxing} which denotes default boxing.
154 *
155 * 2. <b>Static Method #Write:</b><br>
156 * This method is invoked for converting source values to mapped types.
157 * Often the default implementation given in the un-specialized version this struct is
158 * applicable. In this case it can simply be copied to the specialization.
159 *
160 * Custom implementations may use TMP-enabled overloads of method \alib{boxing;Placeholder::Write}
161 * or alternatively write to the \c union members of the placeholder directly.
162 *
163 * 3. <b>Static Method #Read:</b><br>
164 * This method is invoked for converting the placeholder data back to the boxed source type.
165 * Often the default implementation given in the un-specialized version of this struct is
166 * well suited. In this case it can simply be copied to the specialization.<br>
167 * Custom implementations may use TMP-enabled overloads of method \alib{boxing;Placeholder::Read}
168 * or alternatively read the \c union members of the placeholder directly.
169 *
170 * A type becomes \alib{boxing;TT_IsUnboxable;not unboxable} in the moment this function
171 * returns a different type than \p{TBoxable}.<br>
172 * This may well be intended and thus the specialized version of this struct
173 * may declare this method to return \c void.
174 * In this case a declaration of the method is sufficient, as it will never be invoked.<br>
175 * With TMP-enabled specializations of this struct (see Programmer's Manual
176 * chapter \ref alib_boxing_customizing_conditional), the return type might be conditionally set.
177 * Such TMP-defined return type then decides about which of the TMP-enabled types are unboxable
178 * and which are not.
179 *
180 * \note
181 * If a specialization uses default type mapping by providing<br>
182 *
183 * using Mapping= TMappedTo<TDefaultBoxing>;
184 * \note
185 * in theory, a mixture of default and custom boxing is in place!
186 * Note, that the authors of this library and documentation have not seen a use case for this, yet.
187 *
188 * <br><p>
189 * ### Helper Macros: ###
190 *
191 * A set of macros for defining specializations exist.
192 * The use of the macro is recommended, as besides being less error prone, their use make the code
193 * more readable. Finally, chances are good that code that uses the macros remains compatible
194 * with future versions of module \alib_boxing_nl.
195 *
196 * All macros expect this struct's template type \p{TBoxable} as the first parameter, and most
197 * expect the mapped type as the second parameter. The latter must not be wrapped in
198 * templated helpers \b %TMappedTo respectively \b %TMappedToArrayOf, as the macros internally do that.<br>
199 *
200 * For more information, see the reference documentation of the macros, which are:
201 *
202 * - \ref ALIB_BOXING_CUSTOMIZE
203 * - \ref ALIB_BOXING_CUSTOMIZE_TYPE_MAPPING
204 * - \ref ALIB_BOXING_CUSTOMIZE_NOT_UNBOXABLE
205 * - \ref ALIB_BOXING_CUSTOMIZE_ARRAY_TYPE
206 * - \ref ALIB_BOXING_CUSTOMIZE_ARRAY_TYPE_NON_UNBOXABLE
207 * - \ref ALIB_BOXING_CUSTOMIZE_DENY_BOXING
208 *
209 * <br><p>
210 * ### Value Boxing and Nulled Pointers: ###
211 * If a type is boxed as value (either with default boxing or custom boxing) and a \e nulled
212 * pointer to that type is boxed, method \alib{boxing;Placeholder::Clear} is invoked
213 * instead of this struct's method #Write.
214 *
215 * <br><p>
216 * ### Avoiding Seldom Compilation Errors: ###
217 * For technical reasons, namely to avoid TMP compilation problems, some conditional specialization
218 * is internally made, that declare method #Read \c void. This is sometimes needed, if a type is
219 * not returnable, even if that becomes never be boxed or unboxed.
220 * Such situation might happen with TMP, for example if class \b Box is part of a \c union.<br>
221 * The specialization is made for the following types of \p{TBoxable}:
222 * - C++ array types<br>
223 * Those types are fetched by an overloaded constructor that does not (because it can not)
224 * leverage this struct. Likewise, they can not be unboxed in the usual fashion.
225 * - Function types (selected by <c>std::is_function<TBoxable>::value</c>).
226 *
227 * If a dubious error message about method #Read not being able to return a certain type occurs, even
228 * one that a user's code maybe even does "actively" try to box or unbox, then it might be helpful
229 * to specialize this struct for such type, without providing implementations of \b Write and
230 * \b Read and with the latter to return \c void.
231 *
232 * <br><p>
233 * \see More explanation and sample code is given in chapter
234 * \ref alib_boxing_customizing "7. Customizing Boxing" of the
235 * \ref alib_mod_boxing "Programmer's Manual" of module \alib_boxing_nl.
236 *
237 * @tparam TBoxable The source type to customize boxing for.
238 * @tparam TEnableIf Optional TMP parameter to allow conditional specializations.
239 * ************************************************************************************************/
240template<typename TBoxable, typename TEnableIf= void>
242{
243 /**
244 * Defines the mapped type. With specializations, that type has to be wrapped in either
245 * \alib{boxing;TMappedTo;TMappedTo<T>} or \alib{boxing;TMappedTo;TMappedToArrayOf<T>}.
246 * Special designator types \alib{boxing;detail::TDefaultBoxing} and \alib{boxing;detail::TNotBoxable}
247 * may be wrapped, to denote corresponding behavior.
248 *
249 * The default implementation specifies designator type \b TDefaultBoxing, which
250 * disables custom boxing.
251 */
253
254
255 /**
256 * Used for boxing a value, precisely writing the boxable portion of a type into
257 * field \alib{boxing;Box::data}, which is given with parameter \p{target}.<br>
258 * The default implementation of this struct implements this method as follows:
259 * \snippet "alib/boxing/typetraits.inl" DOX_ALIB_BOXING_T_BOXER_WRITE
260 *
261 * This implementation leverages the TMP-enabled overloads \alib{boxing;Placeholder::Write}
262 * and is often all that is needed with custom specializations.
263 *
264 * \see
265 * A possible alternative declaration (signature) of this method is explained with manual
266 * chapter \ref alib_boxing_more_opt_constexpr.
267 *
268 * @param target The placeholder of the destination box.
269 * @param value The value to that is to be boxed.
270 */
271 DOX_MARKER([DOX_ALIB_BOXING_T_BOXER_WRITE])
272 static void Write( Placeholder& target, const TBoxable& value )
273 {
274 target.Write( value );
275 }
276 DOX_MARKER([DOX_ALIB_BOXING_T_BOXER_WRITE])
277
278 /**
279 * Used for unboxing a value, precisely reading the contents of field \alib{boxing;Box::data},
280 * which is given with parameter \p{src} and creating a value of type \p{TBoxable} from
281 * that.<br>
282 * The default implementation of this struct implements this method as follows:
283 * \snippet "alib/boxing/typetraits.inl" DOX_ALIB_BOXING_T_BOXER_READ
284 *
285 * This implementation leverages the TMP-enabled overloads \alib{boxing;Placeholder::Read}
286 * and is often all that is needed with custom specializations.
287 *
288 * If a different type than \p{TBoxable} is returned, then that source type is not unboxable.
289 * To intend such behavior, for example because \p{TBoxable} is mapped to a reduced type
290 * and therefore unboxing is not possible, specializations may declare return type
291 * \c void and omit a definition of this method.<br>
292 * With TMP enabled customizations, also other return types may given, which likewise denote
293 * an unboxable source type. A sample of that is given with Programmer's Manual chapter
294 * \ref alib_boxing_customizing_conditional.
295 *
296 *
297 * @param src The Placeholder to unbox the data from
298 * @return \c The unboxed object.
299 */
300 static
301 ATMP_IF_T_F( !std::is_abstract<TBoxable>::value, TBoxable, TBoxable& )
302 Read( const Placeholder& src)
303 {
304DOX_MARKER([DOX_ALIB_BOXING_T_BOXER_READ])
305return src.Read<TBoxable>();
306DOX_MARKER([DOX_ALIB_BOXING_T_BOXER_READ])
307 }
308
309}; // T_Boxer
310
311// ######################## critical T_Boxer specializations ###########################
312#if !defined(ALIB_DOX)
313
314// This is necessary for types that can't be used as return type in any way, for example
315// types with extents, functions, etc.
316template<typename TBoxable> struct T_Boxer<TBoxable,
317ATMP_VOID_IF( ATMP_IS_ARR( TBoxable ) || std::is_function<TBoxable>::value ) >
318{
319 using Mapping= TMappedTo<detail::TDefaultBoxing>;
320 static void Write( Placeholder& target, TBoxable& value );
321 static void Read ( const Placeholder& src);
322};
323
324// void (needed to pass TMP stuff)
325template<> struct T_Boxer<void>
326{
327 using Mapping= TMappedTo<detail::TDefaultBoxing>;
328 static void Write( Placeholder& target, const void* value );
329 static void* Read ( const Placeholder& src);
330};
331
332#endif
333
334/** ************************************************************************************************
335 * This specializable TMP struct must be set for custom types, if the following applies:
336 * - A custom boxing implements \alib{boxing;T_Boxer::Write} in a way that a different number
337 * of bytes are used in union \alib{boxing;Placeholder} than the \c sizeof() operator reports
338 * on the mapped type's size.
339 * - if the standard copy constructor (used with default boxing) writes a different size.
340 * - One of the above and no specialized version of both box-functions \alib{boxing;FHashcode}
341 * or \alib{boxing;FEquals} are set.
342 *
343 * <b>Background:</b><br>
344 * The default implementations of \alib{boxing;FHashcode} and \alib{boxing;FEquals}
345 * must use the first N "relevant" bytes of the placeholder only. The non-relevant bytes are
346 * not written and therefore must not be taken into account.<br>
347 * To receive the number of relevant bytes, they invoke \alib{boxing;Box::GetPlaceholderUsageLength}
348 * (at run-time). This value is set at compile-time with the creation of a mapped type's \e vtable.
349 * While for array types, the value is set to the overall size of union \alib{boxing;Placeholder},
350 * for non-array types, the value of this TMP struct is used.
351 *
352 * It might be surprising, but a built-in specialization exists for even a C++ fundamental type
353 * <c>long double</c>, which is dependent on the compiler/platform.
354 * For example, on GNU/Linux 64-bit, GCC reports \c 16 with <c>sizeof(long double)</c>.
355 * However, if a <c>long double</c> value is copied, e.g with:
356 *
357 * *pointerToLongDouble= 3.14L;
358 *
359 * then only 10 bytes are written. The reason for this is that <c>sizeof</c> reports the size
360 * needed for alignment when placed in an array of that type.
361 * In the case of \alib_boxing_nl, 6 bytes of the placeholder remain random and therefore
362 * must not be used for hashing or testing values on equality.
363 *
364 * @tparam TMappedPlain The mapped type to modify relevant placeholder length for \b FHashcode
365 * and \b FEquals implementation.
366 **************************************************************************************************/
367template<typename TMappedPlain> struct T_SizeInPlaceholder
368{
369 /** The size used with the placeholder */
370 static constexpr unsigned int value= sizeof(TMappedPlain);
371};
372
373#if !defined(ALIB_DOX)
374 template<> struct T_SizeInPlaceholder<long double> { static constexpr unsigned int value= ALIB_SIZEOF_LONGDOUBLE_WRITTEN; };
375#endif
376
377
378/** ************************************************************************************************
379 * Helper struct that inherits \c std::true_type if boxing is customized for
380 * type \p{T}, otherwise \c std::false_type.
381 *
382 * \see
383 * Helpers \alib{boxing;TT_IsUnboxable}, \alib{boxing;TT_IsLocked} and
384 * \alib{boxing;TT_IsNotBoxable}.
385 *
386 * @tparam T The type to check.
387 * @tparam TEnableIf Used for conditional specializations of this struct.
388 * ************************************************************************************************/
389template<typename T, typename TEnableIf= void> struct TT_IsCustomized : std::true_type {};
390
391#if !defined(ALIB_DOX)
392
393// besides checking T_Boxer<T>, in the case a pointer is given, we also have to check
394// T_Boxer for the type that results when
395// - the pointer is removed and then
396// - a const is removed and finally
397// - the pointer is added again. Otherwise "const T*" is not deferred to "T*"
398
399template<typename T> struct TT_IsCustomized <T, ATMP_VOID_IF(
401 )> : std::false_type {};
402
403template<typename T> struct TT_IsCustomized <T, ATMP_VOID_IF(
404 ATMP_IS_PTR(T) && ATMP_EQ(detail::TDefaultBoxing, typename T_Boxer<ATMP_RCVP(T)*>::Mapping::Type)
405 )> : std::false_type {};
406
407#endif
408
409/** ************************************************************************************************
410 * Helper struct that inherits \c std::true_type if customized boxing is in place
411 * that disallows unboxing, otherwise \c std::false_type.
412 *
413 * This struct is strict in the following sense: It is of \c std::false type, if given \p{T} is a
414 * non-customized value type \b TV, while the corresponding pointer type \b TV* type is locked - and
415 * vice versa.
416 * Note that in these two cases, the type is still not unboxable because it is locked through the
417 * corresponding other customization.
418 *
419 * This behavior is intended and needed internally.
420 *
421 * \note
422 * Unboxing of a type is disabled, if method \alib{boxing;T_Boxer::Read} of a specialized
423 * boxer is declared to return \c void.
424 *
425 * \see
426 * \alib{boxing;TT_IsUnboxable} for an alternative that is of \c std::true_type exactly
427 * if a type can not be unboxed and methods \alib{boxing;Box::IsType} and \alib{boxing;Box::Unbox}
428 * fail to compile with that type.
429 *
430 * @tparam T The type to check.
431 * @tparam TEnableIf Used for conditional specializations of this struct.
432 * ************************************************************************************************/
433template<typename T, typename TEnableIf= void> struct TT_IsLocked : std::false_type {};
434
435#if !defined(ALIB_DOX)
436
437template<typename T > struct TT_IsLocked<T,
438ATMP_VOID_IF( !ATMP_EQ(T, ATMP_RR(decltype(T_Boxer<T>::Read(std::declval<Placeholder>())) ) ) )
439 > : std::true_type {};
440#endif
441
442/** ************************************************************************************************
443 * Helper struct that inherits \c std::true_type, if
444 *
445 * - boxing was customized for the given type and \alib{boxing;detail::TNotBoxable} was given as
446 * mapped type, or
447 * - given type is a value type, no customization is given for it, while the corresponding
448 * pointer type has customized boxing with mapped type being \alib{boxing;detail::TNotBoxable}, or
449 * - given type is a pointer type, no customization is given for it, while the corresponding
450 * value type has customized boxing with mapped type being \alib{boxing;detail::TNotBoxable}.
451 *
452 * If a type is not boxable, it can be neither boxed nor unboxed.
453 *
454 * \see
455 * Helpers \alib{boxing;TT_IsCustomized}, \alib{boxing;TT_IsLocked} and
456 * \alib{boxing;TT_IsUnboxable}.
457 *
458 * @tparam T The type to check.
459 * @tparam TEnableIf Used for conditional specializations of this struct.
460 * ************************************************************************************************/
461template<typename T, typename TEnableIf= void> struct TT_IsNotBoxable : std::false_type {};
462
463#if !defined(ALIB_DOX)
464
465template<typename T>
466struct TT_IsNotBoxable<T, typename std::enable_if<
467 ATMP_EQ(detail::TNotBoxable, typename T_Boxer<T>::Mapping::Type)
468|| ( !TT_IsCustomized<T>::value
469 && ( ( !ATMP_IS_PTR(T)
470 && ATMP_EQ(detail::TNotBoxable , typename T_Boxer< T*>::Mapping::Type) )
471 || ( ATMP_IS_PTR(T)
472 && ATMP_EQ(detail::TNotBoxable , typename T_Boxer<ATMP_RP(T)>::Mapping::Type) )
473 )
474 )
475 >::type> : std::true_type {};
476
477#endif
478
479
480/** ************************************************************************************************
481 * This type is of \c std::true_type exactly if a type can not be unboxed and methods
482 * \alib{boxing;Box::IsType} and \alib{boxing;Box::Unbox} will fail to compile with that type.
483 *
484 * With default boxing, one of the types \b T and \b T* are unboxable (depending on value type
485 * size and whether the type is copy constructible and trivially destructible).
486 *
487 * If custom boxing for either or both of types \b T and \b T* is in place, then the given type is
488 * not unboxable if:
489 * - customization is not in place for the version passed (value or pointer).
490 * - customization is in place for the given type, but \alib{boxing;TT_IsLocked} is of
491 * \c std::true_type.
492 * - The type is mapped to \alib{boxing;detail::TNotBoxable}.
493 *
494 * \see
495 * Helpers \alib{boxing;TT_IsCustomized}, \alib{boxing;TT_IsLocked} and
496 * \alib{boxing;TT_IsNotBoxable}.
497 *
498 * @tparam T The type to check.
499 * @tparam TEnableIf Helper type for implementing specializations of this struct.
500 * ************************************************************************************************/
501template<typename T, typename TEnableIf=void>
502struct TT_IsUnboxable : std::false_type {};
503
504#if !defined(ALIB_DOX)
505
506// default boxing
507template<typename T>
508struct TT_IsUnboxable<T, typename std::enable_if<
509
510 !TT_IsCustomized<ATMP_RP(T) >::value
511&& !TT_IsCustomized<ATMP_RP(T)*>::value
512&& static_cast<bool>( ATMP_IS_PTR(T) )
513 == static_cast<bool>( ( sizeof(Placeholder) < sizeof(ATMP_RCVP(T)) )
514 || !std::is_copy_constructible <ATMP_RCVP(T)>::value
515 || !std::is_trivially_destructible<ATMP_RCVP(T)>::value )
516
517 >::type> : std::true_type {};
518
519
520// custom boxing
521template<typename T>
522struct TT_IsUnboxable<T, typename std::enable_if<
523 TT_IsCustomized<T>::value
524&& !TT_IsLocked <T>::value
525&& !TT_IsNotBoxable<T>::value
526 >::type> : std::true_type {};
527
528
529#endif
530
531}} // namespace [alib::boxing]
532
533//##################################################################################################
534//####################################### Macros ###########################################
535//##################################################################################################
536
537#define ALIB_BOXING_CUSTOMIZE(TSource, TTarget, ...) \
538namespace alib::boxing { \
539template<> struct T_Boxer<TSource> \
540{ \
541 using Mapping= TMappedTo<TTarget>; \
542 __VA_ARGS__ \
543}; } \
544
545#define ALIB_BOXING_CUSTOMIZE_ARRAY_TYPE(TSource, TElement, ...) \
546namespace alib::boxing { \
547template<> struct T_Boxer<TSource> \
548{ \
549 using Mapping= TMappedToArrayOf<TElement>; \
550 __VA_ARGS__ \
551}; }
552
553#define ALIB_BOXING_CUSTOMIZE_TYPE_MAPPING(TSource, TTarget) \
554namespace alib::boxing { \
555template<> struct T_Boxer<TSource> \
556{ using Mapping= TMappedTo<TTarget>; \
557 static void Write( Placeholder& target, TSource const & value ) { target.Write( static_cast<TTarget>( value ) ); } \
558 static TSource Read (const Placeholder& src) { return static_cast<TSource>(src.Read<TTarget>()); } \
559}; }
560
561#define ALIB_BOXING_CUSTOMIZE_TYPE_MAPPING_CONSTEXPR(TSource, TTarget) \
562namespace alib::boxing { \
563template<> struct T_Boxer<TSource> \
564{ using Mapping= TMappedTo<TTarget>; \
565 static constexpr Placeholder Write( TSource const & value ) { return Placeholder( static_cast<TTarget>( value ) );} \
566 static TSource Read (const Placeholder& src) { return static_cast<TSource>(src.Read<TTarget>() );} \
567}; }
568
569
570#define ALIB_BOXING_CUSTOMIZE_NOT_UNBOXABLE(TSource, TTarget) \
571namespace alib::boxing { \
572template<> struct T_Boxer<TSource> \
573{ using Mapping= TMappedTo<TTarget>; \
574 static void Write( Placeholder& target, TSource const & value ) { target.Write( static_cast<typename Mapping::Type>( value ) ); } \
575 static void Read( const Placeholder& src); \
576}; }
577
578#define ALIB_BOXING_CUSTOMIZE_NOT_UNBOXABLE_CONSTEXPR(TSource, TTarget) \
579namespace alib::boxing { \
580template<> struct T_Boxer<TSource> \
581{ using Mapping= TMappedTo<TTarget>; \
582 static constexpr Placeholder Write( TSource const & value ) { return Placeholder( static_cast<typename Mapping::Type>( value ) ); } \
583 static void Read( const Placeholder& src); \
584}; }
585
586
587#define ALIB_BOXING_CUSTOMIZE_ARRAY_TYPE_NON_UNBOXABLE(TSource, TElement, ...) \
588namespace alib::boxing { \
589template<> struct T_Boxer<TSource> \
590{ using Mapping= TMappedToArrayOf<TElement>; \
591 __VA_ARGS__ \
592 static void Read( const Placeholder& src); \
593}; }
594
595
596#define ALIB_BOXING_CUSTOMIZE_DENY_BOXING(TSource) \
597namespace alib::boxing { \
598template<> struct T_Boxer<TSource> \
599{ using Mapping= TMappedTo<detail::TNotBoxable>; \
600 static void Write( Placeholder& target, TSource const & value ); \
601 static void Read ( const Placeholder& src); \
602}; }
603
604#endif // HPP_ALIB_BOXING_TYPETRAITS
#define ATMP_IF_T_F( Cond, T, F)
Definition tmp.hpp:54
#define ATMP_IS_ARR(T)
Definition tmp.hpp:28
#define ATMP_VOID_IF(Cond)
Definition tmp.hpp:52
#define ATMP_RCVP( T)
Definition tmp.hpp:43
#define ATMP_EQ( T, TEqual)
Definition tmp.hpp:32
#define ATMP_IS_PTR(T)
Definition tmp.hpp:27
#define ATMP_RR( T)
Definition tmp.hpp:37
#define ALIB_SIZEOF_LONGDOUBLE_WRITTEN
Definition prepro.dox:30
Definition alib.cpp:57
static Read(const Placeholder &src)
static void Write(Placeholder &target, const TBoxable &value)
TMappedTo< detail::TDefaultBoxing > Mapping
static constexpr unsigned int value