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