/* Type traits for OctaSTD. * * This file is part of OctaSTD. See COPYING.md for futher information. */ #ifndef OCTA_TRAITS_H #define OCTA_TRAITS_H #include #include "octa/types.h" namespace octa { /* forward declarations */ template struct __OctaRemoveCv; template struct __OctaAddLr; template struct __OctaAddRr; template struct __OctaAddConst; template struct IsReference; template struct __OctaRemoveReference; template struct __OctaRemoveAllExtents; template struct IsTriviallyDefaultConstructible; template struct __OctaCommonType; template using RemoveCv = typename __OctaRemoveCv<_T>::Type; template using AddLvalueReference = typename __OctaAddLr<_T>::Type; template using AddRvalueReference = typename __OctaAddRr<_T>::Type; template using AddConst = typename __OctaAddConst<_T>::Type; template using RemoveReference = typename __OctaRemoveReference<_T>::Type; template using RemoveAllExtents = typename __OctaRemoveAllExtents<_T>::Type; /* declval also defined here to avoid including utility.h */ template AddRvalueReference<_T> __octa_declval(); /* integral constant */ template struct IntegralConstant { static constexpr _T value = __val; typedef _T Value; typedef IntegralConstant<_T, __val> Type; constexpr operator Value() const { return value; } constexpr Value operator()() const { return value; } }; typedef IntegralConstant True; typedef IntegralConstant False; template constexpr _T IntegralConstant<_T, val>::value; /* is void */ template struct __OctaIsVoid : False {}; template< > struct __OctaIsVoid: True {}; template struct IsVoid: __OctaIsVoid> {}; /* is null pointer */ template struct __OctaIsNullPointer : False {}; template< > struct __OctaIsNullPointer: True {}; template struct IsNullPointer: __OctaIsNullPointer> {}; /* is integer */ template struct __OctaIsIntegral: False {}; template<> struct __OctaIsIntegral: True {}; template<> struct __OctaIsIntegral: True {}; template<> struct __OctaIsIntegral: True {}; template<> struct __OctaIsIntegral: True {}; template<> struct __OctaIsIntegral: True {}; template<> struct __OctaIsIntegral: True {}; template<> struct __OctaIsIntegral: True {}; template<> struct __OctaIsIntegral: True {}; template<> struct __OctaIsIntegral: True {}; template<> struct __OctaIsIntegral: True {}; template<> struct __OctaIsIntegral: True {}; template<> struct __OctaIsIntegral: True {}; template<> struct __OctaIsIntegral: True {}; template<> struct __OctaIsIntegral: True {}; template<> struct __OctaIsIntegral< wchar_t>: True {}; template struct IsIntegral: __OctaIsIntegral> {}; /* is floating point */ template struct __OctaIsFloatingPoint: False {}; template<> struct __OctaIsFloatingPoint: True {}; template<> struct __OctaIsFloatingPoint: True {}; template<> struct __OctaIsFloatingPoint: True {}; template struct IsFloatingPoint: __OctaIsFloatingPoint> {}; /* is array */ template struct IsArray : False {}; template struct IsArray<_T[] >: True {}; template struct IsArray<_T[_N]>: True {}; /* is pointer */ template struct __OctaIsPointer : False {}; template struct __OctaIsPointer<_T *>: True {}; template struct IsPointer: __OctaIsPointer> {}; /* is lvalue reference */ template struct IsLvalueReference : False {}; template struct IsLvalueReference<_T &>: True {}; /* is rvalue reference */ template struct IsRvalueReference : False {}; template struct IsRvalueReference<_T &&>: True {}; /* is enum */ template struct IsEnum: IntegralConstant {}; /* is union */ template struct IsUnion: IntegralConstant {}; /* is class */ template struct IsClass: IntegralConstant {}; /* is function */ struct __OctaFunctionTestDummy {}; template char __octa_function_test(_T *); template char __octa_function_test(__OctaFunctionTestDummy); template int __octa_function_test(...); template _T &__octa_function_source(int); template __OctaFunctionTestDummy __octa_function_source(...); template::value || IsUnion<_T>::value || IsVoid<_T>::value || IsReference<_T>::value || IsNullPointer<_T>::value > struct __OctaIsFunction: IntegralConstant(__octa_function_source<_T>(0))) == 1 > {}; template struct __OctaIsFunction<_T, true>: False {}; template struct IsFunction: __OctaIsFunction<_T> {}; /* is arithmetic */ template struct IsArithmetic: IntegralConstant::value || IsFloatingPoint<_T>::value) > {}; /* is fundamental */ template struct IsFundamental: IntegralConstant::value || IsVoid<_T>::value || IsNullPointer<_T>::value) > {}; /* is compound */ template struct IsCompound: IntegralConstant::value > {}; /* is pointer to member */ template struct __OctaIsMemberPointer: False {}; template struct __OctaIsMemberPointer<_T _U::*>: True {}; template struct IsMemberPointer: __OctaIsMemberPointer> {}; /* is pointer to member object */ template struct __OctaIsMemberObjectPointer: False {}; template struct __OctaIsMemberObjectPointer<_T _U::*>: IntegralConstant::value > {}; template struct IsMemberObjectPointer: __OctaIsMemberObjectPointer> {}; /* is pointer to member function */ template struct __OctaIsMemberFunctionPointer: False {}; template struct __OctaIsMemberFunctionPointer<_T _U::*>: IntegralConstant::value > {}; template struct IsMemberFunctionPointer: __OctaIsMemberFunctionPointer> {}; /* is reference */ template struct IsReference: IntegralConstant::value || IsRvalueReference<_T>::value) > {}; /* is object */ template struct IsObject: IntegralConstant::value && !IsVoid<_T>::value && !IsReference<_T>::value) > {}; /* is scalar */ template struct IsScalar: IntegralConstant::value || IsPointer<_T>::value || IsEnum<_T>::value || IsNullPointer <_T>::value || IsArithmetic<_T>::value) > {}; /* is abstract */ template struct IsAbstract: IntegralConstant {}; /* is const */ template struct IsConst : False {}; template struct IsConst: True {}; /* is volatile */ template struct IsVolatile : False {}; template struct IsVolatile: True {}; /* is empty */ template struct IsEmpty: IntegralConstant {}; /* is POD */ template struct IsPod: IntegralConstant {}; /* is polymorphic */ template struct IsPolymorphic: IntegralConstant {}; /* is signed */ template struct IsSigned: IntegralConstant {}; /* is unsigned */ template struct IsUnsigned: IntegralConstant {}; /* is standard layout */ template struct IsStandardLayout: IntegralConstant {}; /* is literal type */ template struct IsLiteralType: IntegralConstant {}; /* is trivially copyable */ template struct IsTriviallyCopyable: IntegralConstant>::value > {}; /* is trivial */ template struct IsTrivial: IntegralConstant {}; /* has virtual destructor */ template struct HasVirtualDestructor: IntegralConstant {}; /* is constructible */ #define __OCTA_MOVE(v) static_cast &&>(v) template struct __OctaSelect2nd { typedef _T Type; }; struct __OctaAny { __OctaAny(...); }; template typename __OctaSelect2nd< decltype(__OCTA_MOVE(_T(__octa_declval<_A>()...))), True >::Type __octa_is_ctible_test(_T &&, _A &&...); //#undef __OCTA_MOVE template False __octa_is_ctible_test(__OctaAny, _A &&...); template struct __OctaCtibleCore: __OctaCommonType< decltype(__octa_is_ctible_test(__octa_declval<_T>(), __octa_declval<_A>()...)) >::Type {}; /* function types are not constructible */ template struct __OctaCtibleCore: False {}; /* scalars are default constructible, refs are not */ template struct __OctaCtibleCore: IsScalar<_T> {}; /* scalars and references are constructible from one arg if * implicitly convertible to scalar or reference */ template struct __OctaCtibleRef { static True __test(_T); static False __test(...); }; template struct __OctaCtibleCore: __OctaCommonType< decltype(__OctaCtibleRef<_T>::__test(__octa_declval<_U>())) >::Type {}; /* scalars and references are not constructible from multiple args */ template struct __OctaCtibleCore: False {}; /* treat scalars and refs separately */ template struct __OctaCtibleVoidCheck: __OctaCtibleCore< (IsScalar<_T>::value || IsReference<_T>::value), _T, _A... > {}; /* if any of T or A is void, IsConstructible should be false */ template struct __OctaCtibleVoidCheck: False {}; template struct __OctaCtibleContainsVoid; template<> struct __OctaCtibleContainsVoid<>: False {}; template struct __OctaCtibleContainsVoid<_T, _A...> { static constexpr bool value = IsVoid<_T>::value || __OctaCtibleContainsVoid<_A...>::value; }; /* entry point */ template struct __OctaCtible: __OctaCtibleVoidCheck< __OctaCtibleContainsVoid<_T, _A...>::value || IsAbstract<_T>::value, _T, _A... > {}; /* array types are default constructible if their element type is */ template struct __OctaCtibleCore: __OctaCtible> {}; /* otherwise array types are not constructible by this syntax */ template struct __OctaCtibleCore: False {}; /* incomplete array types are not constructible */ template struct __OctaCtibleCore: False {}; template struct IsConstructible: __OctaCtible<_T, _A...> {}; /* is default constructible */ template struct IsDefaultConstructible: IsConstructible<_T> {}; /* is copy constructible */ template struct IsCopyConstructible: IsConstructible<_T, AddLvalueReference> > {}; /* is move constructible */ template struct IsMoveConstructible: IsConstructible<_T, AddRvalueReference<_T> > {}; /* is assignable */ template typename __OctaSelect2nd< decltype((__octa_declval<_T>() = __octa_declval<_U>())), True >::Type __octa_assign_test(_T &&, _U &&); template False __octa_assign_test(__OctaAny, _T &&); template::value || IsVoid<_U>::value > struct __OctaIsAssignable: __OctaCommonType< decltype(__octa_assign_test(__octa_declval<_T>(), __octa_declval<_U>())) >::Type {}; template struct __OctaIsAssignable<_T, _U, true>: False {}; template struct IsAssignable: __OctaIsAssignable<_T, _U> {}; /* is copy assignable */ template struct IsCopyAssignable: IsAssignable< AddLvalueReference<_T>, AddLvalueReference> > {}; /* is move assignable */ template struct IsMoveAssignable: IsAssignable< AddLvalueReference<_T>, const AddRvalueReference<_T> > {}; /* is destructible */ template struct __OctaIsDtibleApply { typedef int Type; }; template struct IsDestructorWellformed { template static char __test(typename __OctaIsDtibleApply< decltype(__octa_declval<_TT &>().~_TT()) >::Type); template static int __test(...); static constexpr bool value = (sizeof(__test<_T>(12)) == sizeof(char)); }; template struct __OctaDtibleImpl; template struct __OctaDtibleImpl<_T, false>: IntegralConstant>::value > {}; template struct __OctaDtibleImpl<_T, true>: True {}; template struct __OctaDtibleFalse; template struct __OctaDtibleFalse<_T, false> : __OctaDtibleImpl<_T, IsReference<_T>::value> {}; template struct __OctaDtibleFalse<_T, true>: False {}; template struct IsDestructible: __OctaDtibleFalse<_T, IsFunction<_T>::value> {}; template struct IsDestructible<_T[]>: False {}; template< > struct IsDestructible: False {}; /* is trivially constructible */ template struct IsTriviallyConstructible: False {}; template struct IsTriviallyConstructible<_T>: IntegralConstant {}; template struct IsTriviallyConstructible<_T, _T &>: IntegralConstant {}; template struct IsTriviallyConstructible<_T, const _T &>: IntegralConstant {}; template struct IsTriviallyConstructible<_T, _T &&>: IntegralConstant {}; /* is trivially default constructible */ template struct IsTriviallyDefaultConstructible: IsTriviallyConstructible<_T> {}; /* is trivially copy constructible */ template struct IsTriviallyCopyConstructible: IsTriviallyConstructible<_T, AddLvalueReference > {}; /* is trivially move constructible */ template struct IsTriviallyMoveConstructible: IsTriviallyConstructible<_T, AddRvalueReference<_T> > {}; /* is trivially assignable */ template struct IsTriviallyAssignable: False {}; template struct IsTriviallyAssignable<_T>: IntegralConstant {}; template struct IsTriviallyAssignable<_T, _T &>: IntegralConstant {}; template struct IsTriviallyAssignable<_T, const _T &>: IntegralConstant {}; template struct IsTriviallyAssignable<_T, _T &&>: IntegralConstant {}; /* is trivially copy assignable */ template struct IsTriviallyCopyAssignable: IsTriviallyAssignable<_T, AddLvalueReference > {}; /* is trivially move assignable */ template struct IsTriviallyMoveAssignable: IsTriviallyAssignable<_T, AddRvalueReference<_T> > {}; /* is trivially destructible */ template struct IsTriviallyDestructible: IntegralConstant {}; /* is base of */ template struct IsBaseOf: IntegralConstant {}; /* is convertible */ template::value || IsFunction<_T>::value || IsArray<_T>::value > struct __OctaIsConvertible { typedef typename IsVoid<_T>::Type Type; }; template struct __OctaIsConvertible<_F, _T, false> { template static void __test_f(_TT); template(__octa_declval<_FF>())) > static True __test(int); template static False __test(...); typedef decltype(__test<_F, _T>(0)) Type; }; template struct IsConvertible: __OctaIsConvertible<_F, _T>::Type {}; /* type equality */ template struct IsSame : False {}; template struct IsSame<_T, _T>: True {}; /* extent */ template struct Extent: IntegralConstant {}; template struct Extent<_T[], 0>: IntegralConstant {}; template struct Extent<_T[], _I>: IntegralConstant::value> {}; template struct Extent<_T[_N], 0>: IntegralConstant {}; template struct Extent<_T[_N], _I>: IntegralConstant::value> {}; /* rank */ template struct Rank: IntegralConstant {}; template struct Rank<_T[]>: IntegralConstant::value + 1> {}; template struct Rank<_T[_N]>: IntegralConstant::value + 1> {}; /* remove const, volatile, cv */ template struct __OctaRemoveConst { typedef _T Type; }; template struct __OctaRemoveConst { typedef _T Type; }; template struct __OctaRemoveVolatile { typedef _T Type; }; template struct __OctaRemoveVolatile { typedef _T Type; }; template using RemoveConst = typename __OctaRemoveConst<_T>::Type; template using RemoveVolatile = typename __OctaRemoveVolatile<_T>::Type; template struct __OctaRemoveCv { typedef RemoveVolatile> Type; }; /* add const, volatile, cv */ template::value || IsFunction<_T>::value || IsConst<_T>::value> struct __OctaAddConstBase { typedef _T Type; }; template struct __OctaAddConstBase<_T, false> { typedef const _T Type; }; template struct __OctaAddConst { typedef typename __OctaAddConstBase<_T>::Type Type; }; template::value || IsFunction<_T>::value || IsVolatile<_T>::value> struct __OctaAddVolatileBase { typedef _T Type; }; template struct __OctaAddVolatileBase<_T, false> { typedef volatile _T Type; }; template struct __OctaAddVolatile { typedef typename __OctaAddVolatileBase<_T>::Type Type; }; template using AddVolatile = typename __OctaAddVolatile<_T>::Type; template struct __OctaAddCv { typedef AddConst> Type; }; template using AddCv = typename __OctaAddCv<_T>::Type; /* remove reference */ template struct __OctaRemoveReference { typedef _T Type; }; template struct __OctaRemoveReference<_T &> { typedef _T Type; }; template struct __OctaRemoveReference<_T &&> { typedef _T Type; }; /* remove pointer */ template struct __OctaRemovePointer { typedef _T Type; }; template struct __OctaRemovePointer<_T * > { typedef _T Type; }; template struct __OctaRemovePointer<_T * const > { typedef _T Type; }; template struct __OctaRemovePointer<_T * volatile > { typedef _T Type; }; template struct __OctaRemovePointer<_T * const volatile> { typedef _T Type; }; template using RemovePointer = typename __OctaRemovePointer<_T>::Type; /* add pointer */ template struct __OctaAddPointer { typedef RemoveReference<_T> *Type; }; template using AddPointer = typename __OctaAddPointer<_T>::Type; /* add lvalue reference */ template struct __OctaAddLr { typedef _T &Type; }; template struct __OctaAddLr<_T &> { typedef _T &Type; }; template struct __OctaAddLr<_T &&> { typedef _T &Type; }; template<> struct __OctaAddLr { typedef void Type; }; template<> struct __OctaAddLr { typedef const void Type; }; template<> struct __OctaAddLr { typedef volatile void Type; }; template<> struct __OctaAddLr { typedef const volatile void Type; }; /* add rvalue reference */ template struct __OctaAddRr { typedef _T &&Type; }; template struct __OctaAddRr<_T &> { typedef _T &&Type; }; template struct __OctaAddRr<_T &&> { typedef _T &&Type; }; template<> struct __OctaAddRr { typedef void Type; }; template<> struct __OctaAddRr { typedef const void Type; }; template<> struct __OctaAddRr { typedef volatile void Type; }; template<> struct __OctaAddRr { typedef const volatile void Type; }; /* remove extent */ template struct __OctaRemoveExtent { typedef _T Type; }; template struct __OctaRemoveExtent<_T[ ] > { typedef _T Type; }; template struct __OctaRemoveExtent<_T[_N]> { typedef _T Type; }; template using RemoveExtent = typename __OctaRemoveExtent<_T>::Type; /* remove all extents */ template struct __OctaRemoveAllExtents { typedef _T Type; }; template struct __OctaRemoveAllExtents<_T[]> { typedef RemoveAllExtents<_T> Type; }; template struct __OctaRemoveAllExtents<_T[_N]> { typedef RemoveAllExtents<_T> Type; }; /* make (un)signed * * this is bad, but i don't see any better way * shamelessly copied from graphitemaster @ neothyne */ template struct __OctaTl { typedef _T __first; typedef _U __rest; }; /* not a type */ struct __OctaNat { __OctaNat() = delete; __OctaNat(const __OctaNat &) = delete; __OctaNat &operator=(const __OctaNat &) = delete; ~__OctaNat() = delete; }; typedef __OctaTl>>>> __octa_stypes; typedef __OctaTl>>>> __octa_utypes; template struct __OctaTypeFindFirst; template struct __OctaTypeFindFirst<__OctaTl<_T, _U>, _N, true> { typedef _T Type; }; template struct __OctaTypeFindFirst<__OctaTl<_T, _U>, _N, false> { typedef typename __OctaTypeFindFirst<_U, _N>::Type Type; }; template>::value, bool = IsVolatile>::value > struct __OctaApplyCv { typedef _U Type; }; template struct __OctaApplyCv<_T, _U, true, false> { /* const */ typedef const _U Type; }; template struct __OctaApplyCv<_T, _U, false, true> { /* volatile */ typedef volatile _U Type; }; template struct __OctaApplyCv<_T, _U, true, true> { /* const volatile */ typedef const volatile _U Type; }; template struct __OctaApplyCv<_T &, _U, true, false> { /* const */ typedef const _U &Type; }; template struct __OctaApplyCv<_T &, _U, false, true> { /* volatile */ typedef volatile _U &Type; }; template struct __OctaApplyCv<_T &, _U, true, true> { /* const volatile */ typedef const volatile _U &Type; }; template::value || IsEnum<_T>::value> struct __OctaMakeSigned {}; template::value || IsEnum<_T>::value> struct __OctaMakeUnsigned {}; template struct __OctaMakeSigned<_T, true> { typedef typename __OctaTypeFindFirst<__octa_stypes, sizeof(_T)>::Type Type; }; template struct __OctaMakeUnsigned<_T, true> { typedef typename __OctaTypeFindFirst<__octa_utypes, sizeof(_T)>::Type Type; }; template<> struct __OctaMakeSigned {}; template<> struct __OctaMakeSigned { typedef schar Type; }; template<> struct __OctaMakeSigned { typedef schar Type; }; template<> struct __OctaMakeSigned { typedef short Type; }; template<> struct __OctaMakeSigned { typedef short Type; }; template<> struct __OctaMakeSigned { typedef int Type; }; template<> struct __OctaMakeSigned { typedef int Type; }; template<> struct __OctaMakeSigned { typedef long Type; }; template<> struct __OctaMakeSigned { typedef long Type; }; template<> struct __OctaMakeSigned { typedef llong Type; }; template<> struct __OctaMakeSigned { typedef llong Type; }; template<> struct __OctaMakeUnsigned {}; template<> struct __OctaMakeUnsigned { typedef uchar Type; }; template<> struct __OctaMakeUnsigned { typedef uchar Type; }; template<> struct __OctaMakeUnsigned { typedef ushort Type; }; template<> struct __OctaMakeUnsigned { typedef ushort Type; }; template<> struct __OctaMakeUnsigned { typedef uint Type; }; template<> struct __OctaMakeUnsigned { typedef uint Type; }; template<> struct __OctaMakeUnsigned { typedef ulong Type; }; template<> struct __OctaMakeUnsigned { typedef ulong Type; }; template<> struct __OctaMakeUnsigned { typedef ullong Type; }; template<> struct __OctaMakeUnsigned { typedef ullong Type; }; template struct __OctaMakeSignedBase { typedef typename __OctaApplyCv<_T, typename __OctaMakeSigned>::Type >::Type Type; }; template struct __OctaMakeUnsignedBase { typedef typename __OctaApplyCv<_T, typename __OctaMakeUnsigned>::Type >::Type Type; }; template using MakeSigned = typename __OctaMakeSignedBase<_T>::Type; template using MakeUnsigned = typename __OctaMakeUnsignedBase<_T>::Type; /* conditional */ template struct __OctaConditional { typedef _T Type; }; template struct __OctaConditional { typedef _U Type; }; template using Conditional = typename __OctaConditional<_cond, _T, _U>::Type; /* result of call at compile time */ #define __OCTA_FWD(_T, _v) static_cast<_T &&>(_v) template inline auto __octa_rof_invoke(_F &&__f, _A &&...__args) -> decltype(__OCTA_FWD(_F, __f)(__OCTA_FWD(_A, __args)...)) { return __OCTA_FWD(_F, __f)(__OCTA_FWD(_A, __args)...); } template inline auto __octa_rof_invoke(_T _B::*__pmd, _D &&__ref) -> decltype(__OCTA_FWD(_D, __ref).*__pmd) { return __OCTA_FWD(_D, __ref).*__pmd; } template inline auto __octa_rof_invoke(_PMD &&__pmd, _P &&__ptr) -> decltype((*__OCTA_FWD(_P, __ptr)).*__OCTA_FWD(_PMD, __pmd)) { return (*__OCTA_FWD(_P, __ptr)).*__OCTA_FWD(_PMD, __pmd); } template inline auto __octa_rof_invoke(_T _B::*__pmf, _D &&__ref, _A &&...__args) -> decltype((__OCTA_FWD(_D, __ref).*__pmf)(__OCTA_FWD(_A, __args)...)) { return (__OCTA_FWD(_D, __ref).*__pmf)(__OCTA_FWD(_A, __args)...); } template inline auto __octa_rof_invoke(_PMF &&__pmf, _P &&__ptr, _A &&...__args) -> decltype(((*__OCTA_FWD(_P, __ptr)).*__OCTA_FWD(_PMF, __pmf)) (__OCTA_FWD(_A, __args)...)) { return ((*__OCTA_FWD(_P, __ptr)).*__OCTA_FWD(_PMF, __pmf)) (__OCTA_FWD(_A, __args)...); } #undef __OCTA_FWD template struct __OctaResultOf {}; template struct __OctaResultOf<_F(_A...), decltype(void(__octa_rof_invoke( __octa_declval<_F>(), __octa_declval<_A>()...)))> { using type = decltype(__octa_rof_invoke(__octa_declval<_F>(), __octa_declval<_A>()...)); }; template struct __OctaResultOfBase: __OctaResultOf<_T> {}; template using ResultOf = typename __OctaResultOfBase<_T>::Type; /* enable if */ template struct __OctaEnableIf {}; template struct __OctaEnableIf { typedef _T Type; }; template using EnableIf = typename __OctaEnableIf<_B, _T>::Type; /* decay */ template struct __OctaDecay { private: typedef RemoveReference<_T> _U; public: typedef Conditional::value, RemoveExtent<_U> *, Conditional::value, AddPointer<_U>, RemoveCv<_U>> > Type; }; template using Decay = typename __OctaDecay<_T>::Type; /* common type */ template struct __OctaCommonType; template struct __OctaCommonType<_T> { typedef Decay<_T> Type; }; template struct __OctaCommonType<_T, _U> { typedef Decay() : __octa_declval<_U>())> Type; }; template struct __OctaCommonType<_T, _U, _V...> { typedef typename __OctaCommonType::Type, _V...>::Type Type; }; template using CommonType = typename __OctaCommonType<_T, _U, _V...>::Type; /* aligned storage */ template struct __OctaAlignedTest { union type { uchar __data[_N]; octa::max_align_t __align; }; }; template struct __OctaAlignedStorage { struct type { alignas(_A) uchar __data[_N]; }; }; template::Type) > using AlignedStorage = typename __OctaAlignedStorage<_N, _A>::Type; /* aligned union */ template struct __OctaAlignMax; template struct __OctaAlignMax<_N> { static constexpr size_t value = _N; }; template struct __OctaAlignMax<_N1, _N2> { static constexpr size_t value = (_N1 > _N2) ? _N1 : _N2; }; template struct __OctaAlignMax<_N1, _N2, _N...> { static constexpr size_t value = __OctaAlignMax<__OctaAlignMax<_N1, _N2>::value, _N...>::value; }; template struct __OctaAlignedUnion { static constexpr size_t __alignment_value = __OctaAlignMax::value; struct type { alignas(__alignment_value) uchar __data[__OctaAlignMax<_N, sizeof(_T)...>::value]; }; }; template using AlignedUnion = typename __OctaAlignedUnion<_N, _T...>::Type; /* underlying type */ /* gotta wrap, in a struct otherwise clang ICEs... */ template struct __OctaUnderlyingType { typedef __underlying_type(_T) Type; }; template using UnderlyingType = typename __OctaUnderlyingType<_T>::Type; } #endif