53 #define ALIB_TEMPINTERNAL_STATIC_TYPE_CHECKS_BOXING(TBoxable, valueBoxing) \
54 using TVal = ALIB_TVALUE(TBoxable); \
56 constexpr bool isVolatile = std::is_volatile_v<std::remove_pointer_t<TBoxable>>; \
57 constexpr bool isPointer = std::is_pointer<TBoxable>::value; \
58 constexpr bool isValue = !isPointer; \
59 constexpr bool valIsString = IsStringType<TVal>; \
60 constexpr bool isCustomizedTV= IsCustomized<TVal>; \
61 constexpr bool isCustomizedTP= IsCustomized<TPtr>; \
62 constexpr bool isBlockedTV = std::same_as<NotBoxableTag, \
63 typename BoxTraits<TVal>::Mapping>; \
64 constexpr bool isBlockedTP = std::same_as<NotBoxableTag, \
65 typename BoxTraits<TPtr>::Mapping>; \
67 ALIB_STATIC_DENY( GeneralBoxingRule1, !valueBoxing && isVolatile, \
68 "Types boxed as pointers cannot be boxed if volatile." ); \
70 ALIB_STATIC_DENY( GeneralBoxingRule4, isPointer && valIsString, \
71 "String types must not be given as pointers." ); \
73 ALIB_STATIC_DENY( CustomBoxingRule3, isBlockedTV && isValue, \
74 "Customized boxing forbids boxing this value type: " \
75 "'BoxTraits<T>::Type == NotBoxable'!" ); \
77 ALIB_STATIC_DENY( CustomBoxingRule4, isBlockedTP && isPointer, \
78 "Customized boxing forbids boxing this pointer type: " \
79 "'BoxTraits<T*>::Type == NotBoxable'!" ); \
81 ALIB_STATIC_DENY( CustomBoxingRule5, isBlockedTV && !isCustomizedTP && isPointer, \
82 "Customized boxing forbids boxing value type T (BoxTraits<T>::Type == NotBoxable), while " \
83 "no customization for this pointer type T* was given." ); \
85 ALIB_STATIC_DENY( CustomBoxingRule6, isBlockedTP && !isCustomizedTV && isValue, \
86 "Customized boxing forbids boxing pointer type T* " \
87 "(BoxTraits<T*>::Type == NotBoxable), while no customization for this value type T was " \
91 #define ALIB_TEMPINTERNAL_STATIC_TYPE_CHECKS_UNBOXING(TUnboxable) \
92 using TVal = ALIB_TVALUE(TUnboxable); \
94 constexpr bool isConst = std::is_const_v <std::remove_pointer_t<TUnboxable>>; \
95 constexpr bool isVolatile = std::is_volatile_v<std::remove_pointer_t<TUnboxable>>; \
96 constexpr bool isPointer = std::is_pointer<TUnboxable>::value; \
97 constexpr bool isValue = !isPointer; \
98 constexpr bool valuesFit = sizeof(std::conditional_t<std::same_as<void,TVal>,void*,TVal>)\
99 <= sizeof(Placeholder); \
100 constexpr bool isCopyConstr = std::is_copy_constructible<TVal>::value; \
101 constexpr bool isTrivDest = std::is_trivially_destructible<TVal>::value; \
102 constexpr bool isCustomizedTV= IsCustomized<TVal>; \
103 constexpr bool isCustomizedTP= IsCustomized<TPtr>; \
104 constexpr bool isDefault = !(isCustomizedTV || isCustomizedTP); \
105 constexpr bool isBlockedTV = std::same_as<NotBoxableTag, \
106 typename BoxTraits<TVal>::Mapping>; \
107 constexpr bool isBlockedTP = std::same_as<NotBoxableTag, \
108 typename BoxTraits<TPtr>::Mapping>; \
109 constexpr bool isLockedTV = IsLocked<TVal>; \
110 constexpr bool isLockedTP = IsLocked<TPtr>; \
113 ALIB_STATIC_DENY( GeneralBoxingRule2, isConst, \
114 "Type qualifier 'const' not allowed with template type TUnboxable. Types boxed as values" \
115 " are always unboxed mutable, types boxed as pointers are always unboxed constant." ); \
117 ALIB_STATIC_DENY( GeneralBoxingRule3, isVolatile, \
118 "Type qualifier 'volatile' not allowed with template type TUnboxable" ); \
121 ALIB_STATIC_DENY( DefaultBoxingRule1, isDefault && isValue && !valuesFit, \
122 "This type cannot be unboxed by value: " \
123 "By default, values that do not fit into boxes are boxed as pointers." ); \
125 ALIB_STATIC_DENY( DefaultBoxingRule2, \
126 isDefault && isValue && (!isCopyConstr || !isTrivDest), \
127 "This type cannot be unboxed by value: " \
128 "By default, types that are not copy-constructible or not trivially destructible, " \
129 "are boxed as pointers." ); \
131 ALIB_STATIC_DENY( DefaultBoxingRule3, \
132 isDefault && isPointer && valuesFit && isCopyConstr && isTrivDest, \
133 "This type cannot be unboxed as pointer: Default boxing of types that fit " \
134 "into boxes and are copy-constructible and trivially destructible, " \
135 "is performed by value." ); \
139 ALIB_STATIC_DENY( CustomBoxingRule1, isCustomizedTV && !isCustomizedTP && isPointer, \
140 "This pointer type T* cannot be unboxed, because custom boxing is defined for " \
141 "value type T, while no custom boxing is defined for pointer type T*." ); \
143 ALIB_STATIC_DENY( CustomBoxingRule2, !isCustomizedTV && isCustomizedTP && isValue, \
144 "This value type T cannot be unboxed, because custom boxing is defined for " \
145 "pointer type T*, while no custom boxing is defined for value type T." ); \
149 ALIB_STATIC_DENY( CustomBoxingRule3, isBlockedTV && isValue, \
150 "Customized boxing forbids unboxing (and even boxing) this value type: " \
151 "'BoxTraits<T>::Type == NotBoxable'!" ); \
153 ALIB_STATIC_DENY( CustomBoxingRule4, isBlockedTP && isPointer, \
154 "Customized boxing forbids unboxing (and even boxing) this pointer type: " \
155 "'BoxTraits<T*>::Type == NotBoxable'!" ); \
157 ALIB_STATIC_DENY( CustomBoxingRule5, isBlockedTV && !isCustomizedTP && isPointer, \
158 "Customized boxing forbids unboxing (and even boxing) value type T " \
159 "(BoxTraits<T>::Type == NotBoxable), while no customization for this pointer type T* " \
162 ALIB_STATIC_DENY( CustomBoxingRule6, isBlockedTP && !isCustomizedTV && isValue, \
163 "Customized boxing forbids unboxing (and even boxing) pointer type T* " \
164 "(BoxTraits<T*>::Type == NotBoxable), while no customization for this value type T was" \
168 ALIB_STATIC_DENY( CustomBoxingRule7, isLockedTV && isValue, \
169 "Customized boxing forbids unboxing this value type: " \
170 "'BoxTraits<T>::Read' returns a different type." ); \
172 ALIB_STATIC_DENY( CustomBoxingRule8, isLockedTP && isPointer, \
173 "Customized boxing forbids unboxing this pointer type: " \
174 "'BoxTraits<T*>::Read' returns a different type." ); \
176 ALIB_STATIC_DENY( CustomBoxingRule9, isLockedTV && !isCustomizedTP && isPointer, \
177 "Customized boxing forbids unboxing value type T " \
178 "('BoxTraits<T>::Read' returns a different type), while no customization for this pointer " \
179 "type T* was given." ); \
181 ALIB_STATIC_DENY( CustomBoxingRule10, isLockedTP && !isCustomizedTV && isValue, \
182 "Customized boxing forbids unboxing pointer type T* " \
183 "('BoxTraits<T*>::Read' returns a different type), while no customization for this value " \
184 "type T was given." ); \
193 template<
typename TBoxable>
195 using TCV= std::remove_cv_t<TBoxable>;
197 if constexpr (std::same_as<typename BoxTraits<TCV>::Mapping,
DefaultBoxingTag>)
209 constexpr void initPH(
const T& src)
noexcept
237 ,
data (placeholder) {}
250 template <
typename TBoxable>
251 inline constexpr Box(
const TBoxable& src )
noexcept;
256 constexpr Box(
const std::nullptr_t& ) noexcept :
vtable(
nullptr) {}
260 requires std::is_array_v<T>
261 constexpr Box( T& src )
noexcept {
262 using TElem= std::remove_cv_t<std::remove_pointer_t<std::decay_t<T>>>;
266 : std::extent<T>::value;
272 requires ( std::is_base_of<Box, std::remove_cv_t<T>>::value )
273 constexpr Box(
const T& src ) noexcept
275 ,
data ( src.data ) {}
281 requires ( IsStringType<std::remove_cv_t<T>> )
282 constexpr Box(
const T& src )
noexcept {
284 ALIB_TEMPINTERNAL_STATIC_TYPE_CHECKS_BOXING(T,
true)
285 if constexpr ( characters::ArrayTraits <T,
nchar>::Access == characters::Policy::Implicit ) {
287 data = Placeholder( characters::ArrayTraits<std::remove_cv_t<T>,
nchar>::Buffer( src ),
288 characters::ArrayTraits<std::remove_cv_t<T>,
nchar>::Length( src ) );
292 data = Placeholder( characters::ArrayTraits<std::remove_cv_t<T>,
wchar>::Buffer( src ),
293 characters::ArrayTraits<std::remove_cv_t<T>,
wchar>::Length( src ) );
297 data = Placeholder( characters::ArrayTraits<std::remove_cv_t<T>,
xchar>::Buffer( src ),
298 characters::ArrayTraits<std::remove_cv_t<T>,
xchar>::Length( src ) );
305 requires ( !std::is_pointer_v<T>
306 && !IsStringType<std::remove_cv_t<T>>
307 && ( IsCustomized<std::decay_t<T> >
308 || ( !IsCustomized<std::decay_t<T>*> && IsStdPH<T> ) )
310 constexpr Box(
const T& src )
noexcept {
311 ALIB_TEMPINTERNAL_STATIC_TYPE_CHECKS_BOXING(T,
true)
318 requires( !std::is_pointer_v<T>
319 && !IsStringType<std::remove_cv_t<T>>
320 && !std::is_array_v<T>
321 && !std::is_base_of_v<
Box, T>
322 && !IsCustomized<std::decay_t<T> >
323 && ( IsCustomized<std::remove_cv_t<T> >
324 || ( !IsCustomized<std::decay_t<T>*> && !IsStdPH<T> )
325 || ( IsCustomized<std::decay_t<T>*> )
328 constexpr
Box( const T& src ) noexcept {
329 ALIB_TEMPINTERNAL_STATIC_TYPE_CHECKS_BOXING(T,
true)
336 requires ( std::is_pointer_v<T>
339 ( IsCustomized<std::remove_cv_t<T>>
342 constexpr
Box( const T& src ) noexcept {
343 ALIB_TEMPINTERNAL_STATIC_TYPE_CHECKS_BOXING(T,
false)
350 requires ( std::is_pointer_v<T>
352 && !IsStringType<std::remove_cv_t<T>>
354 ( IsCustomized<std::remove_cv_t<T>>
358 constexpr
Box( const T& src ) noexcept {
359 ALIB_TEMPINTERNAL_STATIC_TYPE_CHECKS_BOXING(T,
false)
362 if ( src )
initPH( *src );
363 else
data = Placeholder( sizeof(TV) <= sizeof(
integer)
369 #undef ALIB_TEMPINTERNAL_STATIC_TYPE_CHECKS_BOXING
370 #undef ALIB_TM_IS_DEFAULT_BOXING
410 template<
typename TBoxable>
414 template<
typename TBoxable>
427 template<
typename TBoxable>
428 requires ( !std::same_as<TBoxable, void>
431 ALIB_TEMPINTERNAL_STATIC_TYPE_CHECKS_UNBOXING(TBoxable)
435 template<
typename TBoxable>
436 requires std::same_as<TBoxable, void>
440 #if !ALIB_FEAT_BOXING_BIJECTIVE_INTEGRALS || DOXYGEN
497 #if !ALIB_FEAT_BOXING_BIJECTIVE_CHARACTERS || DOXYGEN
561 template<
typename TElementType>
563 {
return vtable &&
typeid(TElementType) ==
vtable->ElementType; }
609 template<
typename TValue>
610 requires ( !std::is_pointer_v<TValue>
614 template<
typename TValue>
616 TValue
Unbox()
const {
617 ALIB_TEMPINTERNAL_STATIC_TYPE_CHECKS_UNBOXING(TValue)
621 "Cannot unbox string-type <{}> from mapped type <{}>.", &
typeid(TValue), &
vtable->Type )
634 template<
typename TValue>
635 requires ( !std::is_pointer_v<TValue>
637 TValue
Unbox()
const {
638 ALIB_TEMPINTERNAL_STATIC_TYPE_CHECKS_UNBOXING(TValue)
642 "Cannot unbox type <{}> from mapped type <{}>.", &typeid(TValue), &
vtable->Type )
647 template<typename TPointer>
648 requires ( std::is_pointer_v<TPointer>
650 const std::remove_pointer_t<TPointer>*
Unbox()
const {
651 ALIB_TEMPINTERNAL_STATIC_TYPE_CHECKS_UNBOXING(TPointer)
655 "Cannot unbox type <{}> from mapped type <{}>.", &typeid(TPointer), &
vtable->Type )
661 #undef ALIB_TEMPINTERNAL_STATIC_TYPE_CHECKS_UNBOXING
670 template <
typename TPo
inter>
671 requires std::is_pointer_v<TPointer>
713 return vtable->PlaceholderUsage;
735 data.Array.Pointer=
nullptr;
736 data.Array.Length = 0;
780 return vtable->ElementType;
802 template <
typename TElementType>
806 "Box::UnboxArray() invoked on box of non-array type <{}>.", &
vtable->Type )
809 "BOXING: Cannot unbox array type<{}[]> from mapped type<{}[]>.",
810 &
typeid(TElementType*), &
vtable->ElementType )
813 return data.GetPointer<TElementType>();
830 return data.GetLength();
844 template <
typename TElementType>
847 "Box is void (no contents). Unboxing is undefined behavior." )
849 "Box::UnboxElement() invoked on box of non-array type <{}>.", &
vtable->Type )
852 "BOXING: Cannot unbox array element type <{}> from mapped type <{}[]>.",
853 &
typeid(TElementType), &
vtable->ElementType )
856 "Box::UnboxElement<{}>(): Index out of bounds.", &
typeid(TElementType))
860 return *(
data.GetPointer<TElementType>() + idx );
907 template <
typename TFDecl>
910 ,
bool isInvocation =
false )
const;
912 template <
typename TFDecl>
914 ALIB_DBG( ,
bool isInvocation =
false) )
const {
920 auto result=
vtable->Functions.Get<TFDecl>(
ALIB_DBG(isInvocation) );
969 template <
typename TFDecl,
typename... TArgs>
970 decltype( std::declval<typename TFDecl::Signature>()( std::declval<Box&>(), std::declval<TArgs>()... ) )
973 if( func !=
nullptr )
974 return reinterpret_cast<typename TFDecl::Signature
>(func)
975 ( *
this, std::forward<TArgs>(args)... );
978 return decltype( std::declval<typename TFDecl::Signature>()( std::declval<Box&>(),
979 std::declval<TArgs>()... )) ();
992 template <
typename TFDecl,
typename... TArgs>
993 decltype( std::declval<typename TFDecl::Signature>()( std::declval<Box&>(), std::declval<TArgs>()... ) )
994 CallDirect(typename TFDecl::Signature function, TArgs&&... args)
const {
996 "Box not initialized (does not contain value). Function call not allowed." )
997 return reinterpret_cast<typename TFDecl::Signature
>(function)
998 ( *
this, std::forward<TArgs>(args)... );
1017 template <
typename TFDecl,
typename... TArgs>
1018 decltype( std::declval<typename TFDecl::Signature>()( std::declval<Box&>(), std::declval<TArgs>()... ) )
1021 "Box not initialized (does not contain value). Function call not allowed." )
1023 if( func !=
nullptr )
1024 return reinterpret_cast<typename TFDecl::Signature
>(func)
1025 ( *
this, std::forward<TArgs>(args)... );
1027 return decltype( std::declval<typename TFDecl::Signature>()( std::declval<Box&>(),
1028 std::declval<TArgs>()... )) ();
1042 template <
typename TFDecl,
typename... TArgs>
1043 decltype( std::declval<typename TFDecl::Signature>()( std::declval<Box&>(), std::declval<TArgs>()... ) )
1044 CallDirect(typename TFDecl::Signature function, TArgs &&... args) {
1046 "Box not initialized (does not contain value). Function call not allowed." )
1047 return reinterpret_cast<typename TFDecl::Signature
>( function )
1048 ( *
this, std::forward<TArgs>(args)... );
1101 explicit operator bool()
const;