52 #define ALIB_TEMPINTERNAL_STATIC_TYPE_CHECKS_BOXING(TBoxable, valueBoxing) \
53 using TVal = ALIB_TVALUE(TBoxable); \
55 constexpr bool isVolatile = std::is_volatile_v<std::remove_pointer_t<TBoxable>>; \
56 constexpr bool isPointer = std::is_pointer<TBoxable>::value; \
57 constexpr bool isValue = !isPointer; \
58 constexpr bool valIsString = IsStringType<TVal>; \
59 constexpr bool isCustomizedTV= IsCustomized<TVal>; \
60 constexpr bool isCustomizedTP= IsCustomized<TPtr>; \
61 constexpr bool isBlockedTV = std::same_as<NotBoxableTag, \
62 typename BoxTraits<TVal>::Mapping>; \
63 constexpr bool isBlockedTP = std::same_as<NotBoxableTag, \
64 typename BoxTraits<TPtr>::Mapping>; \
66 ALIB_STATIC_DENY( GeneralBoxingRule1, !valueBoxing && isVolatile, \
67 "Types boxed as pointers cannot be boxed if volatile." ); \
69 ALIB_STATIC_DENY( GeneralBoxingRule4, isPointer && valIsString, \
70 "String types must not be given as pointers." ); \
72 ALIB_STATIC_DENY( CustomBoxingRule3, isBlockedTV && isValue, \
73 "Customized boxing forbids boxing this value type: " \
74 "'BoxTraits<T>::Type == NotBoxable'!" ); \
76 ALIB_STATIC_DENY( CustomBoxingRule4, isBlockedTP && isPointer, \
77 "Customized boxing forbids boxing this pointer type: " \
78 "'BoxTraits<T*>::Type == NotBoxable'!" ); \
80 ALIB_STATIC_DENY( CustomBoxingRule5, isBlockedTV && !isCustomizedTP && isPointer, \
81 "Customized boxing forbids boxing value type T (BoxTraits<T>::Type == NotBoxable), while " \
82 "no customization for this pointer type T* was given." ); \
84 ALIB_STATIC_DENY( CustomBoxingRule6, isBlockedTP && !isCustomizedTV && isValue, \
85 "Customized boxing forbids boxing pointer type T* " \
86 "(BoxTraits<T*>::Type == NotBoxable), while no customization for this value type T was " \
90 #define ALIB_TEMPINTERNAL_STATIC_TYPE_CHECKS_UNBOXING(TUnboxable) \
91 using TVal = ALIB_TVALUE(TUnboxable); \
93 constexpr bool isConst = std::is_const_v <std::remove_pointer_t<TUnboxable>>; \
94 constexpr bool isVolatile = std::is_volatile_v<std::remove_pointer_t<TUnboxable>>; \
95 constexpr bool isPointer = std::is_pointer<TUnboxable>::value; \
96 constexpr bool isValue = !isPointer; \
97 constexpr bool valuesFit = sizeof(std::conditional_t<std::same_as<void,TVal>,void*,TVal>)\
98 <= sizeof(Placeholder); \
99 constexpr bool isCopyConstr = std::is_copy_constructible<TVal>::value; \
100 constexpr bool isTrivDest = std::is_trivially_destructible<TVal>::value; \
101 constexpr bool isCustomizedTV= IsCustomized<TVal>; \
102 constexpr bool isCustomizedTP= IsCustomized<TPtr>; \
103 constexpr bool isDefault = !(isCustomizedTV || isCustomizedTP); \
104 constexpr bool isBlockedTV = std::same_as<NotBoxableTag, \
105 typename BoxTraits<TVal>::Mapping>; \
106 constexpr bool isBlockedTP = std::same_as<NotBoxableTag, \
107 typename BoxTraits<TPtr>::Mapping>; \
108 constexpr bool isLockedTV = IsLocked<TVal>; \
109 constexpr bool isLockedTP = IsLocked<TPtr>; \
112 ALIB_STATIC_DENY( GeneralBoxingRule2, isConst, \
113 "Type qualifier 'const' not allowed with template type TUnboxable. Types boxed as values" \
114 " are always unboxed mutable, types boxed as pointers are always unboxed constant." ); \
116 ALIB_STATIC_DENY( GeneralBoxingRule3, isVolatile, \
117 "Type qualifier 'volatile' not allowed with template type TUnboxable" ); \
120 ALIB_STATIC_DENY( DefaultBoxingRule1, isDefault && isValue && !valuesFit, \
121 "This type cannot be unboxed by value: " \
122 "By default, values that do not fit into boxes are boxed as pointers." ); \
124 ALIB_STATIC_DENY( DefaultBoxingRule2, \
125 isDefault && isValue && (!isCopyConstr || !isTrivDest), \
126 "This type cannot be unboxed by value: " \
127 "By default, types that are not copy-constructible or not trivially destructible, " \
128 "are boxed as pointers." ); \
130 ALIB_STATIC_DENY( DefaultBoxingRule3, \
131 isDefault && isPointer && valuesFit && isCopyConstr && isTrivDest, \
132 "This type cannot be unboxed as pointer: Default boxing of types that fit " \
133 "into boxes and are copy-constructible and trivially destructible, " \
134 "is performed by value." ); \
138 ALIB_STATIC_DENY( CustomBoxingRule1, isCustomizedTV && !isCustomizedTP && isPointer, \
139 "This pointer type T* cannot be unboxed, because custom boxing is defined for " \
140 "value type T, while no custom boxing is defined for pointer type T*." ); \
142 ALIB_STATIC_DENY( CustomBoxingRule2, !isCustomizedTV && isCustomizedTP && isValue, \
143 "This value type T cannot be unboxed, because custom boxing is defined for " \
144 "pointer type T*, while no custom boxing is defined for value type T." ); \
148 ALIB_STATIC_DENY( CustomBoxingRule3, isBlockedTV && isValue, \
149 "Customized boxing forbids unboxing (and even boxing) this value type: " \
150 "'BoxTraits<T>::Type == NotBoxable'!" ); \
152 ALIB_STATIC_DENY( CustomBoxingRule4, isBlockedTP && isPointer, \
153 "Customized boxing forbids unboxing (and even boxing) this pointer type: " \
154 "'BoxTraits<T*>::Type == NotBoxable'!" ); \
156 ALIB_STATIC_DENY( CustomBoxingRule5, isBlockedTV && !isCustomizedTP && isPointer, \
157 "Customized boxing forbids unboxing (and even boxing) value type T " \
158 "(BoxTraits<T>::Type == NotBoxable), while no customization for this pointer type T* " \
161 ALIB_STATIC_DENY( CustomBoxingRule6, isBlockedTP && !isCustomizedTV && isValue, \
162 "Customized boxing forbids unboxing (and even boxing) pointer type T* " \
163 "(BoxTraits<T*>::Type == NotBoxable), while no customization for this value type T was" \
167 ALIB_STATIC_DENY( CustomBoxingRule7, isLockedTV && isValue, \
168 "Customized boxing forbids unboxing this value type: " \
169 "'BoxTraits<T>::Read' returns a different type." ); \
171 ALIB_STATIC_DENY( CustomBoxingRule8, isLockedTP && isPointer, \
172 "Customized boxing forbids unboxing this pointer type: " \
173 "'BoxTraits<T*>::Read' returns a different type." ); \
175 ALIB_STATIC_DENY( CustomBoxingRule9, isLockedTV && !isCustomizedTP && isPointer, \
176 "Customized boxing forbids unboxing value type T " \
177 "('BoxTraits<T>::Read' returns a different type), while no customization for this pointer " \
178 "type T* was given." ); \
180 ALIB_STATIC_DENY( CustomBoxingRule10, isLockedTP && !isCustomizedTV && isValue, \
181 "Customized boxing forbids unboxing pointer type T* " \
182 "('BoxTraits<T*>::Read' returns a different type), while no customization for this value " \
183 "type T was given." ); \
192 template<
typename TBoxable>
194 using TCV= std::remove_cv_t<TBoxable>;
196 if constexpr (std::same_as<typename BoxTraits<TCV>::Mapping,
DefaultBoxingTag>)
208 constexpr void initPH(
const T& src)
noexcept
230 ,
data (placeholder) {}
243 template <
typename TBoxable>
244 inline constexpr Box(
const TBoxable& src )
noexcept;
249 constexpr Box(
const std::nullptr_t& ) noexcept :
vtable(
nullptr) {}
253 requires std::is_array_v<T>
254 constexpr Box( T& src )
noexcept {
255 using TElem= std::remove_cv_t<std::remove_pointer_t<std::decay_t<T>>>;
259 : std::extent<T>::value;
265 requires ( std::is_base_of<Box, std::remove_cv_t<T>>::value )
266 constexpr Box(
const T& src ) noexcept
268 ,
data ( src.data ) {}
274 requires ( IsStringType<std::remove_cv_t<T>> )
275 constexpr Box(
const T& src )
noexcept {
277 ALIB_TEMPINTERNAL_STATIC_TYPE_CHECKS_BOXING(T,
true)
278 if constexpr ( characters::ArrayTraits <T,
nchar>::Access == characters::Policy::Implicit ) {
280 data = Placeholder( characters::ArrayTraits<std::remove_cv_t<T>,
nchar>::Buffer( src ),
281 characters::ArrayTraits<std::remove_cv_t<T>,
nchar>::Length( src ) );
285 data = Placeholder( characters::ArrayTraits<std::remove_cv_t<T>,
wchar>::Buffer( src ),
286 characters::ArrayTraits<std::remove_cv_t<T>,
wchar>::Length( src ) );
290 data = Placeholder( characters::ArrayTraits<std::remove_cv_t<T>,
xchar>::Buffer( src ),
291 characters::ArrayTraits<std::remove_cv_t<T>,
xchar>::Length( src ) );
298 requires ( !std::is_pointer_v<T>
299 && !IsStringType<std::remove_cv_t<T>>
300 && ( IsCustomized<std::decay_t<T> >
301 || ( !IsCustomized<std::decay_t<T>*> && IsStdPH<T> ) )
303 constexpr Box(
const T& src )
noexcept {
304 ALIB_TEMPINTERNAL_STATIC_TYPE_CHECKS_BOXING(T,
true)
311 requires( !std::is_pointer_v<T>
312 && !IsStringType<std::remove_cv_t<T>>
313 && !std::is_array_v<T>
314 && !std::is_base_of_v<
Box, T>
315 && !IsCustomized<std::decay_t<T> >
316 && ( IsCustomized<std::remove_cv_t<T> >
317 || ( !IsCustomized<std::decay_t<T>*> && !IsStdPH<T> )
318 || ( IsCustomized<std::decay_t<T>*> )
321 constexpr
Box( const T& src ) noexcept {
322 ALIB_TEMPINTERNAL_STATIC_TYPE_CHECKS_BOXING(T,
true)
329 requires ( std::is_pointer_v<T>
332 ( IsCustomized<std::remove_cv_t<T>>
335 constexpr
Box( const T& src ) noexcept {
336 ALIB_TEMPINTERNAL_STATIC_TYPE_CHECKS_BOXING(T,
false)
343 requires ( std::is_pointer_v<T>
345 && !IsStringType<std::remove_cv_t<T>>
347 ( IsCustomized<std::remove_cv_t<T>>
351 constexpr
Box( const T& src ) noexcept {
352 ALIB_TEMPINTERNAL_STATIC_TYPE_CHECKS_BOXING(T,
false)
355 if ( src )
initPH( *src );
356 else
data = Placeholder( sizeof(TV) <= sizeof(
integer)
362 #undef ALIB_TEMPINTERNAL_STATIC_TYPE_CHECKS_BOXING
363 #undef ALIB_TM_IS_DEFAULT_BOXING
403 template<
typename TBoxable>
407 template<
typename TBoxable>
420 template<
typename TBoxable>
421 requires ( !std::same_as<TBoxable, void>
424 ALIB_TEMPINTERNAL_STATIC_TYPE_CHECKS_UNBOXING(TBoxable)
428 template<
typename TBoxable>
429 requires std::same_as<TBoxable, void>
433 #if !ALIB_FEAT_BOXING_BIJECTIVE_INTEGRALS || DOXYGEN
490 #if !ALIB_FEAT_BOXING_BIJECTIVE_CHARACTERS || DOXYGEN
554 template<
typename TElementType>
556 {
return vtable &&
typeid(TElementType) ==
vtable->ElementType; }
602 template<
typename TValue>
603 requires ( !std::is_pointer_v<TValue>
607 template<
typename TValue>
609 TValue
Unbox()
const {
610 ALIB_TEMPINTERNAL_STATIC_TYPE_CHECKS_UNBOXING(TValue)
614 "Cannot unbox string-type <{}> from mapped type <{}>.", &
typeid(TValue), &
vtable->Type )
627 template<
typename TValue>
628 requires ( !std::is_pointer_v<TValue>
630 TValue
Unbox()
const {
631 ALIB_TEMPINTERNAL_STATIC_TYPE_CHECKS_UNBOXING(TValue)
635 "Cannot unbox type <{}> from mapped type <{}>.", &typeid(TValue), &
vtable->Type )
640 template<typename TPointer>
641 requires ( std::is_pointer_v<TPointer>
643 const std::remove_pointer_t<TPointer>*
Unbox()
const {
644 ALIB_TEMPINTERNAL_STATIC_TYPE_CHECKS_UNBOXING(TPointer)
648 "Cannot unbox type <{}> from mapped type <{}>.", &typeid(TPointer), &
vtable->Type )
654 #undef ALIB_TEMPINTERNAL_STATIC_TYPE_CHECKS_UNBOXING
663 template <
typename TPo
inter>
664 requires std::is_pointer_v<TPointer>
706 return vtable->PlaceholderUsage;
728 data.Array.Pointer=
nullptr;
729 data.Array.Length = 0;
773 return vtable->ElementType;
795 template <
typename TElementType>
799 "Box::UnboxArray() invoked on box of non-array type <{}>.", &
vtable->Type )
802 "BOXING: Cannot unbox array type<{}[]> from mapped type<{}[]>.",
803 &
typeid(TElementType*), &
vtable->ElementType )
806 return data.GetPointer<TElementType>();
823 return data.GetLength();
837 template <
typename TElementType>
840 "Box is void (no contents). Unboxing is undefined behavior." )
842 "Box::UnboxElement() invoked on box of non-array type <{}>.", &
vtable->Type )
845 "BOXING: Cannot unbox array element type <{}> from mapped type <{}[]>.",
846 &
typeid(TElementType), &
vtable->ElementType )
849 "Box::UnboxElement<{}>(): Index out of bounds.", &
typeid(TElementType))
853 return *(
data.GetPointer<TElementType>() + idx );
900 template <
typename TFDecl>
903 ,
bool isInvocation =
false )
const;
905 template <
typename TFDecl>
907 ALIB_DBG( ,
bool isInvocation =
false) )
const {
913 auto result=
vtable->Functions.Get<TFDecl>(
ALIB_DBG(isInvocation) );
962 template <
typename TFDecl,
typename... TArgs>
963 decltype( std::declval<typename TFDecl::Signature>()( std::declval<Box&>(), std::declval<TArgs>()... ) )
966 if( func !=
nullptr )
967 return reinterpret_cast<typename TFDecl::Signature
>(func)
968 ( *
this, std::forward<TArgs>(args)... );
971 return decltype( std::declval<typename TFDecl::Signature>()( std::declval<Box&>(),
972 std::declval<TArgs>()... )) ();
985 template <
typename TFDecl,
typename... TArgs>
986 decltype( std::declval<typename TFDecl::Signature>()( std::declval<Box&>(), std::declval<TArgs>()... ) )
987 CallDirect(typename TFDecl::Signature function, TArgs&&... args)
const {
989 "Box not initialized (does not contain value). Function call not allowed." )
990 return reinterpret_cast<typename TFDecl::Signature
>(function)
991 ( *
this, std::forward<TArgs>(args)... );
1010 template <
typename TFDecl,
typename... TArgs>
1011 decltype( std::declval<typename TFDecl::Signature>()( std::declval<Box&>(), std::declval<TArgs>()... ) )
1014 "Box not initialized (does not contain value). Function call not allowed." )
1016 if( func !=
nullptr )
1017 return reinterpret_cast<typename TFDecl::Signature
>(func)
1018 ( *
this, std::forward<TArgs>(args)... );
1020 return decltype( std::declval<typename TFDecl::Signature>()( std::declval<Box&>(),
1021 std::declval<TArgs>()... )) ();
1035 template <
typename TFDecl,
typename... TArgs>
1036 decltype( std::declval<typename TFDecl::Signature>()( std::declval<Box&>(), std::declval<TArgs>()... ) )
1037 CallDirect(typename TFDecl::Signature function, TArgs &&... args) {
1039 "Box not initialized (does not contain value). Function call not allowed." )
1040 return reinterpret_cast<typename TFDecl::Signature
>( function )
1041 ( *
this, std::forward<TArgs>(args)... );
1094 explicit operator bool()
const;