8#ifndef HPP_ALIB_BOXING_BOX
9#define HPP_ALIB_BOXING_BOX 1
11#if !defined(HPP_ALIB_BOXING_BOXING)
12# error "ALib sources with ending '.inl' must not be included from outside."
20namespace alib {
namespace boxing {
63 #define ALIB_TEMPINTERNAL_STATIC_TYPE_CHECKS_BOXING(TBoxable, TClean) \
64 using TVal = typename std::remove_pointer<ATMP_RCVR(TBoxable)>::type; \
66 constexpr bool valueBoxing = !ATMP_IS_PTR(TClean); \
67 constexpr bool isVolatile = std::is_volatile<ATMP_RP(TBoxable)>::value; \
68 constexpr bool isPointer = std::is_pointer<TBoxable>::value; \
69 constexpr bool isValue = !isPointer; \
70 constexpr bool isCustomizedTV= TT_IsCustomized<TVal>::value; \
71 constexpr bool isCustomizedTP= TT_IsCustomized<TPtr>::value; \
72 constexpr bool isBlockedTV = ATMP_EQ( detail::TNotBoxable, typename T_Boxer<TVal>::Mapping::Type ); \
73 constexpr bool isBlockedTP = ATMP_EQ( detail::TNotBoxable, typename T_Boxer<TPtr>::Mapping::Type ); \
75 ALIB_STATIC_DENY( GeneralBoxingRule1, !valueBoxing && isVolatile, \
76 "Types boxed as pointers cannot be boxed if volatile." ); \
78 ALIB_STATIC_DENY( CustomBoxingRule3, isBlockedTV && isValue, \
79 "Customized boxing forbids boxing this value type: " \
80 "'T_Boxer<T>::Type == NotBoxable'!" ); \
82 ALIB_STATIC_DENY( CustomBoxingRule4, isBlockedTP && isPointer, \
83 "Customized boxing forbids boxing this pointer type: " \
84 "'T_Boxer<T*>::Type == NotBoxable'!" ); \
86 ALIB_STATIC_DENY( CustomBoxingRule5, isBlockedTV && !isCustomizedTP && isPointer, \
87 "Customized boxing forbids boxing value type T (T_Boxer<T>::Type == NotBoxable), while " \
88 "no customization for this pointer type T* was given." ); \
90 ALIB_STATIC_DENY( CustomBoxingRule6, isBlockedTP && !isCustomizedTV && isValue, \
91 "Customized boxing forbids boxing pointer type T* " \
92 "(T_Boxer<T*>::Type == NotBoxable), while no customization for this value type T was " \
97 #define ALIB_TEMPINTERNAL_STATIC_TYPE_CHECKS_UNBOXING(TUnboxable) \
98 using T = ATMP_RCVR(TUnboxable); \
99 using TVal = typename std::remove_pointer<T>::type; \
100 using TPtr = TVal*; \
101 constexpr bool isConst = std::is_const <ATMP_RP(TUnboxable)>::value; \
102 constexpr bool isVolatile = std::is_volatile<ATMP_RP(TUnboxable)>::value; \
103 constexpr bool isPointer = std::is_pointer<TUnboxable>::value; \
104 constexpr bool isValue = !isPointer; \
105 constexpr bool valuesFit = sizeof(ATMP_IF_T_F(ATMP_EQ(void,TVal), void*,TVal)) \
106 <= sizeof(Placeholder); \
107 constexpr bool isConstructible= std::is_copy_constructible<TVal>::value; \
108 constexpr bool isTriviallyDest= std::is_trivially_destructible<TVal>::value; \
109 constexpr bool isCustomizedTV = TT_IsCustomized<TVal>::value; \
110 constexpr bool isCustomizedTP = TT_IsCustomized<TPtr>::value; \
111 constexpr bool isDefault = !(isCustomizedTV || isCustomizedTP); \
112 constexpr bool isBlockedTV = ATMP_EQ( detail::TNotBoxable, typename T_Boxer<TVal>::Mapping::Type ); \
113 constexpr bool isBlockedTP = ATMP_EQ( detail::TNotBoxable, typename T_Boxer<TPtr>::Mapping::Type ); \
114 constexpr bool isLockedTV = TT_IsLocked<TVal>::value; \
115 constexpr bool isLockedTP = TT_IsLocked<TPtr>::value; \
118 ALIB_STATIC_DENY( GeneralBoxingRule2, isConst, \
119 "Type qualifier 'const' not allowed with template type TUnboxable. Types boxed as values"\
120 " are always unboxed mutable, types boxed as pointers are always unboxed constant." ); \
122 ALIB_STATIC_DENY( GeneralBoxingRule3, isVolatile, \
123 "Type qualifier 'volatile' not allowed with template type TUnboxable" ); \
126 ALIB_STATIC_DENY( DefaultBoxingRule1, isDefault && isValue && !valuesFit, \
127 "This type cannot be unboxed by value: " \
128 "By default, values that do not fit into boxes are boxed as pointers." ); \
130 ALIB_STATIC_DENY( DefaultBoxingRule2, \
131 isDefault && isValue && (!isConstructible || !isTriviallyDest), \
132 "This type cannot be unboxed by value: " \
133 "By default, types that are not copy constructible or not trivially destructible, " \
134 "are boxed as pointers." ); \
136 ALIB_STATIC_DENY( DefaultBoxingRule3, \
137 isDefault && isPointer && valuesFit && isConstructible && isTriviallyDest, \
138 "This type cannot be unboxed as pointer: Default boxing of types that fit " \
139 "into boxes and are copy constructible and trivially destructible, " \
140 "is performed by value." ); \
144 ALIB_STATIC_DENY( CustomBoxingRule1, isCustomizedTV && !isCustomizedTP && isPointer, \
145 "This pointer type T* cannot be unboxed, because custom boxing is defined for " \
146 "value type T, while no custom boxing is defined for pointer type T*." ); \
148 ALIB_STATIC_DENY( CustomBoxingRule2, !isCustomizedTV && isCustomizedTP && isValue, \
149 "This value type T cannot be unboxed, because custom boxing is defined for " \
150 "pointer type T*, while no custom boxing is defined for value type T." ); \
154 ALIB_STATIC_DENY( CustomBoxingRule3, isBlockedTV && isValue, \
155 "Customized boxing forbids unboxing (and even boxing) this value type: " \
156 "'T_Boxer<T>::Type == NotBoxable'!" ); \
158 ALIB_STATIC_DENY( CustomBoxingRule4, isBlockedTP && isPointer, \
159 "Customized boxing forbids unboxing (and even boxing) this pointer type: " \
160 "'T_Boxer<T*>::Type == NotBoxable'!" ); \
162 ALIB_STATIC_DENY( CustomBoxingRule5, isBlockedTV && !isCustomizedTP && isPointer, \
163 "Customized boxing forbids unboxing (and even boxing) value type T " \
164 "(T_Boxer<T>::Type == NotBoxable), while no customization for this pointer type T* " \
167 ALIB_STATIC_DENY( CustomBoxingRule6, isBlockedTP && !isCustomizedTV && isValue, \
168 "Customized boxing forbids unboxing (and even boxing) pointer type T* " \
169 "(T_Boxer<T*>::Type == NotBoxable), while no customization for this value type T was" \
173 ALIB_STATIC_DENY( CustomBoxingRule7, isLockedTV && isValue, \
174 "Customized boxing forbids unboxing this value type: " \
175 "'T_Boxer<T>::Read' returns a different type." ); \
177 ALIB_STATIC_DENY( CustomBoxingRule8, isLockedTP && isPointer, \
178 "Customized boxing forbids unboxing this pointer type: " \
179 "'T_Boxer<T*>::Read' returns a different type." ); \
181 ALIB_STATIC_DENY( CustomBoxingRule9, isLockedTV && !isCustomizedTP && isPointer, \
182 "Customized boxing forbids unboxing value type T " \
183 "('T_Boxer<T>::Read' returns a different type), while no customization for this pointer "\
184 "type T* was given." ); \
186 ALIB_STATIC_DENY( CustomBoxingRule10, isLockedTP && !isCustomizedTV && isValue, \
187 "Customized boxing forbids unboxing pointer type T* " \
188 "('T_Boxer<T*>::Read' returns a different type), while no customization for this value " \
189 "type T was given." ); \
199 template<
typename TBoxable,
bool NoStaticAsserts= false>
205 template<
typename TBoxable>
252 Box& operator=( const
Box& ) noexcept = default;
258 Box& operator=(
Box&& ) noexcept = default;
263 ~
Box() noexcept = default;
270 ,
data (placeholder) {}
285 template <
typename TBoxable>
286 inline constexpr Box(
const TBoxable& src )
noexcept;
291 ATMP_SELECT_IF_1TP(
typename TNullptr, std::is_same<std::nullptr_t, TNullptr>::value )
293 Box(
const TNullptr& ) noexcept
302 Box( T& src ) noexcept
305 || std::is_same<
ATMP_RECVP(T),
wchar_t >::value
306 || std::is_same<
ATMP_RECVP(T),
char16_t>::value
307 || std::is_same<
ATMP_RECVP(T),
char32_t>::value
318 Box(
const T& src ) noexcept
330 constexpr
Box(const T& src ) noexcept
340 && ( ( !TT_IsCustomized<
ATMP_RCVR(T)*>::value
341 &&
sizeof(Placeholder) >=
sizeof(
ATMP_RCVP(T))
342 && std::is_copy_constructible <
ATMP_RCVP(T)>::value
343 && std::is_trivially_destructible<
ATMP_RCVP(T)>::value )
344 || TT_IsCustomized<
ATMP_RCVR(T) >::value )
346 Box(const T& src ) noexcept
350 ALIB_TEMPINTERNAL_STATIC_TYPE_CHECKS_BOXING(T,
ATMP_RCV(T))
360 && !TT_IsCustomized <
ATMP_RCVR(T) >::value
361 && !TT_IsCustomized <
ATMP_RCVR(T)*>::value
363 && ( (
sizeof(Placeholder) <
sizeof(
ATMP_RCVP(T)))
364 || !std::is_copy_constructible <
ATMP_RCVP(T)>::value
365 || !std::is_trivially_destructible<
ATMP_RCVP(T)>::value ) )
367 Box(
const T& src ) noexcept
369 ,
data ( Placeholder( &src ) )
375 && !TT_IsCustomized <
ATMP_RCVR(T) >::value
377 constexpr
Box(const T& src ) noexcept
385 && !TT_IsCustomized <
ATMP_RCVR(T) >::value
386 && TT_IsCustomized <
ATMP_RCVR(T)*>::value
388 Box(const T& src ) noexcept
392 ALIB_TEMPINTERNAL_STATIC_TYPE_CHECKS_BOXING(T,
ATMP_RCV(T)*)
405 && ( (sizeof(Placeholder) < sizeof(
ATMP_RCVP(T)))
406 || !std::is_copy_constructible <
ATMP_RCVP(T)>::value
407 || !std::is_trivially_destructible<
ATMP_RCVP(T)>::value ) )
408 constexpr
Box(const T& srcP ) noexcept
410 ,
data ( Placeholder( srcP ) )
416 && !std::is_const<T>::value
418 constexpr
Box(const T& srcP ) noexcept
427 && std::is_const<
ATMP_RP(T)>::value
429 constexpr
Box(const T& srcP ) noexcept
431 ,
data ( T_Boxer <T>::Write( srcP ) )
439 Box(const T& srcP ) noexcept
443 ALIB_TEMPINTERNAL_STATIC_TYPE_CHECKS_BOXING(T,
ATMP_RCVP(T)*)
453 && ( !std::is_const<
ATMP_RP(T)>::value
456 constexpr
Box(const T& srcP ) noexcept
461 : Placeholder( static_cast<
integer>(0), static_cast<
integer>(0) ) )
468 && !TT_IsCustomized<
ATMP_RCVR(T) >::value
469 && ( TT_IsCustomized<
ATMP_RCVP(T) >::value
470 || (
sizeof(Placeholder) >=
sizeof(
ATMP_RCVP(T) )
471 && std::is_copy_constructible <
ATMP_RCVP(T)>::value
472 && std::is_trivially_destructible<
ATMP_RCVP(T)>::value ) )
474 Box(const T& srcP ) noexcept
478 ALIB_TEMPINTERNAL_STATIC_TYPE_CHECKS_BOXING(T,
ATMP_RCVP(T))
483 ?
sizeof(Placeholder)
492 #undef ALIB_TEMPINTERNAL_STATIC_TYPE_CHECKS_BOXING
493 #undef ALIB_TM_IS_DEFAULT_BOXING
539 template<
typename TBoxable>
545 template<
typename TBoxable>
552 template<
typename TBoxable>
556 ALIB_TEMPINTERNAL_STATIC_TYPE_CHECKS_UNBOXING(TBoxable)
562 #if !ALIB_FEAT_BOXING_BIJECTIVE_INTEGRALS || DOXYGEN
639 #if !ALIB_FEAT_BOXING_BIJECTIVE_CHARACTERS || DOXYGEN
724 template<
typename TElementType>
786 template<
typename TUnboxable>
791 template <
typename TUnboxable>
797 ALIB_TEMPINTERNAL_STATIC_TYPE_CHECKS_UNBOXING(TUnboxable)
801 "Cannot unbox type <" , lang::DbgTypeDemangler(typeid(TUnboxable)).Get(),
802 "> from mapped type <", lang::DbgTypeDemangler(
vtable->Type ).Get(),
809 #undef ALIB_TEMPINTERNAL_STATIC_TYPE_CHECKS_UNBOXING
822 template<
typename TUnboxable>
827 template <
typename TUnboxable>
986 template <
typename TElementType>
990 "Box not initialized. Unboxing is undefined behavior." )
992 "Box::UnboxArray() invoked on box of non-array type <",
1037 template <
typename TElementType>
1041 "Box is void (no contents). Unboxing is undefined behavior." )
1043 "Box::UnboxElement() invoked on box of non-array type <",
1053 ">(): Index out of bounds.")
1108 template <
typename TFDecl>
1111 ,
bool isInvocation =
false )
const;
1113 template <
typename TFDecl>
1115 ALIB_DBG( ,
bool isInvocation =
false) )
const
1173 template <
typename TFDecl,
typename... TArgs>
1174 decltype( std::declval<typename TFDecl::Signature>()( std::declval<Box&>(), std::declval<TArgs>()... ) )
1178 if( func !=
nullptr )
1179 return reinterpret_cast<typename TFDecl::Signature
>(func)
1180 ( *
this, std::forward<TArgs>(args)... );
1183 return decltype( std::declval<typename TFDecl::Signature>()( std::declval<Box&>(),
1184 std::declval<TArgs>()... )) ();
1199 template <
typename TFDecl,
typename... TArgs>
1200 decltype( std::declval<typename TFDecl::Signature>()( std::declval<Box&>(), std::declval<TArgs>()... ) )
1201 CallDirect(typename TFDecl::Signature function, TArgs&&... args)
const
1204 "Box not initialized (does not contain value). Function call not allowed." )
1205 return reinterpret_cast<typename TFDecl::Signature
>(function)
1206 ( *
this, std::forward<TArgs>(args)... );
1227 template <
typename TFDecl,
typename... TArgs>
1228 decltype( std::declval<typename TFDecl::Signature>()( std::declval<Box&>(), std::declval<TArgs>()... ) )
1232 "Box not initialized (does not contain value). Function call not allowed." )
1234 if( func !=
nullptr )
1235 return reinterpret_cast<typename TFDecl::Signature
>(func)
1236 ( *
this, std::forward<TArgs>(args)... );
1238 return decltype( std::declval<typename TFDecl::Signature>()( std::declval<Box&>(),
1239 std::declval<TArgs>()... )) ();
1255 template <
typename TFDecl,
typename... TArgs>
1256 decltype( std::declval<typename TFDecl::Signature>()( std::declval<Box&>(), std::declval<TArgs>()... ) )
1257 CallDirect(typename TFDecl::Signature function, TArgs &&... args)
1260 "Box not initialized (does not contain value). Function call not allowed." )
1261 return reinterpret_cast<typename TFDecl::Signature
>( function )
1262 ( *
this, std::forward<TArgs>(args)... );
1283 return ! ((*this) == rhs);
1325 return !( (*this) < rhs);
1335 explicit operator bool()
const;
1382namespace alib {
namespace boxing {
decltype(std::declval< typename TFDecl::Signature >()(std::declval< Box & >(), std::declval< TArgs >()...)) CallDirect(typename TFDecl::Signature function, TArgs &&... args) const
uinteger UnboxUnsignedIntegral() const
Box(Box &&) noexcept=default
Trivial default move constructor.
ALIB_API bool operator<(Box const &rhs) const
void Import(TypeCode typeCode, const Placeholder &placeholder)
size_t ArrayElementSize() const
TElementType * UnboxArray() const
ALIB_API bool IsNotNull() const
TypeCode ExportType() const
constexpr Box(const TBoxable &src) noexcept
wchar UnboxCharacter() const
bool operator>=(Box const &rhs) const
integer UnboxLength() const
TElementType & UnboxElement(integer idx) const
bool IsFloatingPoint() const
bool IsSameType(const Box &other) const
TFDecl::Signature GetFunction(Reach searchScope, bool isInvocation=false) const
void Import(TypeCode typeCode)
TUnboxable UnboxMutable() const
bool IsUnsignedIntegral() const
ALIB_API size_t Hashcode() const
bool IsSignedIntegral() const
unsigned int GetPlaceholderUsageLength() const
ALIB_API bool operator<=(Box const &rhs) const
Box(const Box &) noexcept=default
Trivial default copy constructor.
ALIB_API double UnboxFloatingPoint() const
Placeholder data
The data that we encapsulate.
bool operator!=(const Box &rhs) const
uinteger TypeCode
The type of type codes received with ExportType.
decltype(std::declval< typename TFDecl::Signature >()(std::declval< Box & >(), std::declval< TArgs >()...)) Call(TArgs &&... args) const
const detail::VTable * DbgGetVTable() const
const std::type_info & TypeID() const
const std::type_info & ElementTypeID() const
const Placeholder & Data() const
integer UnboxSignedIntegral() const
ALIB_API bool operator>(Box const &rhs) const
ALIB_API bool operator==(Box const &rhs) const
ALIB_API void Clone(MonoAllocator &memory)
const TUnboxable Unbox() const
static detail::VTable * getVTable()
Placeholder ExportValue() const
ALIB_API const char * Get()
#define ATMP_IF_T_F( Cond, T, F)
#define ATMP_ISOF( T, TBase)
#define ALIB_WARNINGS_RESTORE
#define ALIB_FORCE_INLINE
#define ATMP_EQ( T, TEqual)
#define ALIB_ASSERT_ERROR(cond,...)
#define ALIB_WARNINGS_ALLOW_UNSAFE_BUFFER_USAGE
#define ATMP_SELECT_IF_1TP(TParam, ...)
#define ATMP_T_IF(T, Cond)
ALIB_API void DbgCheckRegistration(detail::VTable *vtable, bool increaseUsageCounter)
FunctionTable DEFAULT_FUNCTIONS
The default box-functions set.
const alib::boxing::Box & Type
Reach
Denotes the reach of something.
@ Global
Denotes global reach.
lang::uinteger uinteger
Type alias in namespace alib.
characters::wchar wchar
Type alias in namespace alib.
lang::integer integer
Type alias in namespace alib.
TMapped Type
The given type TMapped.
static void Write(Placeholder &target, const TBoxable &value)
TFDecl::Signature Get(bool isInvocation) const
FunctionTable Functions
Box-functions attached with BootstrapRegister.
const std::type_info & Type
const unsigned int PlaceholderUsage
const MappingType Mapping
const std::type_info & ElementType
constexpr TReturn * Pointer() const
constexpr void SetUInteger(int idx, uinteger value)
constexpr integer Length() const
ALIB_WARNINGS_RESTORE constexpr void Clear()