/* 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" #include "octa/utility.h" /* libc++ and cppreference.com occasionally used for reference */ /* missing: * * UnderlyingType */ namespace octa { template struct RemoveConstVolatile; /* integral constant */ template struct IntegralConstant { static constexpr T value = val; typedef T value_type; typedef IntegralConstant type; constexpr operator value_type() const { return value; } constexpr value_type operator()() const { return value; } }; typedef IntegralConstant true_t; typedef IntegralConstant false_t; template constexpr T IntegralConstant::value; /* is void */ template struct IsVoidBase : false_t {}; template< > struct IsVoidBase: true_t {}; template struct IsVoid: IsVoidBase::type> {}; /* is null pointer */ template struct IsNullPointerBase : false_t {}; template< > struct IsNullPointerBase: true_t {}; template struct IsNullPointer: IsNullPointerBase< typename RemoveConstVolatile::type > {}; /* is integer */ template struct IsIntegralBase: false_t {}; template<> struct IsIntegralBase: true_t {}; template<> struct IsIntegralBase: true_t {}; template<> struct IsIntegralBase: true_t {}; template<> struct IsIntegralBase: true_t {}; template<> struct IsIntegralBase: true_t {}; template<> struct IsIntegralBase: true_t {}; template<> struct IsIntegralBase: true_t {}; template<> struct IsIntegralBase: true_t {}; template<> struct IsIntegralBase: true_t {}; template<> struct IsIntegralBase: true_t {}; template<> struct IsIntegralBase: true_t {}; template<> struct IsIntegralBase: true_t {}; template struct IsIntegral: IsIntegralBase::type> {}; /* is floating point */ template struct IsFloatingPointBase : false_t {}; template<> struct IsFloatingPointBase: true_t {}; template<> struct IsFloatingPointBase: true_t {}; template<> struct IsFloatingPointBase: true_t {}; template struct IsFloatingPoint: IsFloatingPointBase::type> {}; /* is array */ template struct IsArray : false_t {}; template struct IsArray: true_t {}; template struct IsArray: true_t {}; /* is pointer */ template struct IsPointerBase : false_t {}; template struct IsPointerBase: true_t {}; template struct IsPointer: IsPointerBase::type> {}; /* is lvalue reference */ template struct IsLvalueReference : false_t {}; template struct IsLvalueReference: true_t {}; /* is rvalue reference */ template struct IsRvalueReference : false_t {}; template struct IsRvalueReference: true_t {}; /* is enum */ template struct IsEnum: IntegralConstant {}; /* is union */ template struct IsUnion: IntegralConstant {}; /* is class */ template struct IsClass: IntegralConstant {}; /* is function */ template struct IsReference; namespace internal { struct FunctionTestDummy {}; template char function_test(T *); template char function_test(FunctionTestDummy); template int function_test(...); template T &function_source(int); template FunctionTestDummy function_source(...); } template::value || IsUnion::value || IsVoid::value || IsReference::value || IsNullPointer::value > struct IsFunctionBase: IntegralConstant(internal::function_source(0))) == 1 > {}; template struct IsFunctionBase: false_t {}; template struct IsFunction: IsFunctionBase {}; /* is arithmetic */ template struct IsArithmetic: IntegralConstant::value || IsFloatingPoint::value) > {}; /* is fundamental */ template struct IsFundamental: IntegralConstant::value || IsVoid::value || IsNullPointer::value) > {}; /* is compound */ template struct IsCompound: IntegralConstant::value > {}; /* is pointer to member */ template struct IsMemberPointerBase: false_t {}; template struct IsMemberPointerBase: true_t {}; template struct IsMemberPointer: IsMemberPointerBase< typename RemoveConstVolatile::type > {}; /* is pointer to member object */ template struct IsMemberObjectPointerBase: false_t {}; template struct IsMemberObjectPointerBase: IntegralConstant::value > {}; template struct IsMemberObjectPointer: IsMemberObjectPointerBase::type> {}; /* is pointer to member function */ template struct IsMemberFunctionPointerBase: false_t {}; template struct IsMemberFunctionPointerBase: IntegralConstant::value > {}; template struct IsMemberFunctionPointer: IsMemberFunctionPointerBase::type> {}; /* is reference */ template struct IsReference: IntegralConstant::value || IsRvalueReference::value) > {}; /* is object */ template struct IsObject: IntegralConstant::value && !IsVoid::value && !IsReference::value) > {}; /* is scalar */ template struct IsScalar: IntegralConstant::value || IsPointer::value || IsEnum::value || IsNullPointer ::value || IsArithmetic::value) > {}; /* is abstract */ template struct IsAbstract: IntegralConstant {}; /* is const */ template struct IsConst : false_t {}; template struct IsConst: true_t {}; /* is volatile */ template struct IsVolatile : false_t {}; template struct IsVolatile: true_t {}; /* 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 RemoveAllExtents; template struct IsStandardLayout: IntegralConstant::type>::value > {}; /* is literal type */ template struct IsLiteralType: IntegralConstant::type>::value || IsStandardLayout::value > {}; /* is trivially copyable */ template struct IsTriviallyCopyable: IntegralConstant::type>::value > {}; /* is trivial */ template struct IsTriviallyDefaultConstructible; template struct IsTrivial: IntegralConstant::value && IsTriviallyDefaultConstructible::value) > {}; /* has virtual destructor */ template struct HasVirtualDestructor: IntegralConstant {}; /* is destructible - libc++ used as ref */ template struct IsDestructibleApply { typedef int type; }; template struct IsDestructorWellformed { template static char test(typename IsDestructibleApply< decltype(declval().~TT()) >::type); template static int test(...); static constexpr bool value = (sizeof(test(12)) == sizeof(char)); }; template struct DestructibleImpl; template struct DestructibleImpl: IntegralConstant::type>::value > {}; template struct DestructibleImpl: true_t {}; template struct DestructibleFalse; template struct DestructibleFalse : DestructibleImpl::value> {}; template struct DestructibleFalse: false_t {}; template struct IsDestructible: DestructibleFalse::value> {}; template struct IsDestructible: false_t {}; template< > struct IsDestructible: false_t {}; /* is trivially constructible */ template struct IsTriviallyConstructible: false_t {}; template struct IsTriviallyConstructible: IntegralConstant {}; template struct IsTriviallyConstructible: IntegralConstant {}; template struct IsTriviallyConstructible: IntegralConstant {}; template struct IsTriviallyConstructible: IntegralConstant {}; /* is trivially default constructible */ template struct IsTriviallyDefaultConstructible: IsTriviallyConstructible {}; /* is trivially copy constructible */ template struct AddLvalueReference; template struct IsTriviallyCopyConstructible: IsTriviallyConstructible::type > {}; /* is trivially move constructible */ template struct IsTriviallyMoveConstructible: IsTriviallyConstructible::type > {}; /* is trivially assignable */ template struct IsTriviallyAssignable: false_t {}; template struct IsTriviallyAssignable: IntegralConstant {}; template struct IsTriviallyAssignable: IntegralConstant {}; template struct IsTriviallyAssignable: IntegralConstant {}; template struct IsTriviallyAssignable: IntegralConstant {}; /* is trivially copy assignable */ template struct AddLvalueReference; template struct IsTriviallyCopyAssignable: IsTriviallyAssignable::type > {}; /* is trivially move assignable */ template struct IsTriviallyMoveAssignable: IsTriviallyAssignable::type > {}; /* is trivially destructible */ template struct IsTriviallyDestructible: IntegralConstant {}; /* is nothrow constructible */ template struct IsNothrowConstructible: false_t {}; template struct IsNothrowConstructible: IntegralConstant {}; template struct IsNothrowConstructible: IntegralConstant {}; template struct IsNothrowConstructible: IntegralConstant {}; template struct IsNothrowConstructible: IntegralConstant {}; /* is nothrow default constructible */ template struct IsNothrowDefaultConstructible: IsNothrowConstructible {}; /* is nothrow copy constructible */ template struct AddLvalueReference; template struct IsNothrowCopyConstructible: IsNothrowConstructible::type > {}; /* is nothrow move constructible */ template struct IsNothrowMoveConstructible: IsNothrowConstructible::type > {}; /* is nothrow assignable */ template struct IsNothrowAssignable: false_t {}; template struct IsNothrowAssignable: IntegralConstant {}; template struct IsNothrowAssignable: IntegralConstant {}; template struct IsNothrowAssignable: IntegralConstant {}; template struct IsNothrowAssignable: IntegralConstant {}; /* is nothrow copy assignable */ template struct AddLvalueReference; template struct IsNothrowCopyAssignable: IsNothrowAssignable::type > {}; /* is nothrow move assignable */ template struct IsNothrowMoveAssignable: IsNothrowAssignable::type > {}; /* is nothrow destructible */ template struct IsNothrowDestructibleBase; template struct IsNothrowDestructibleBase: IntegralConstant().~T()) > {}; template struct IsNothrowDestructible: IsNothrowDestructibleBase::value > {}; template struct IsNothrowDestructible: IsNothrowDestructible {}; template struct IsNothrowDestructible: IsNothrowDestructible {}; template struct IsNothrowDestructible: IsNothrowDestructible {}; /* is base of */ template struct IsBaseOf: IntegralConstant {}; /* is convertible */ template::value || IsFunction::value || IsArray::value > struct IsConvertibleBase { typedef typename IsVoid::type type; }; template struct IsConvertibleBase { template static void test_f(TT); template(declval())) > static true_t test(int); template static false_t test(...); typedef decltype(test(0)) type; }; template struct IsConvertible: IsConvertibleBase::type {}; /* type equality */ template struct IsSame : false_t {}; template struct IsSame: true_t {}; /* extent */ template struct Extent: IntegralConstant {}; template struct Extent: IntegralConstant {}; template struct Extent: IntegralConstant::value> {}; template struct Extent: IntegralConstant {}; template struct Extent: IntegralConstant::value> {}; /* rank */ template struct Rank: IntegralConstant {}; template struct Rank: IntegralConstant::value + 1> {}; template struct Rank: IntegralConstant::value + 1> {}; /* remove const, volatile, cv */ template struct RemoveConst { typedef T type; }; template struct RemoveConst { typedef T type; }; template struct RemoveVolatile { typedef T type; }; template struct RemoveVolatile { typedef T type; }; template struct RemoveConstVolatile { typedef typename RemoveVolatile::type>::type type; }; /* add const, volatile, cv */ template::value || IsFunction::value || IsConst::value> struct AddConstBase { typedef T type; }; template struct AddConstBase { typedef const T type; }; template struct AddConst { typedef typename AddConstBase::type type; }; template::value || IsFunction::value || IsVolatile::value> struct AddVolatileBase { typedef T type; }; template struct AddVolatileBase { typedef volatile T type; }; template struct AddVolatile { typedef typename AddVolatileBase::type type; }; template struct AddConstVolatile { typedef typename AddConst::type>::type type; }; /* remove reference */ template using RemoveReference = internal::RemoveReference; /* remove pointer */ template struct RemovePointer { typedef T type; }; template struct RemovePointer { typedef T type; }; template struct RemovePointer { typedef T type; }; template struct RemovePointer { typedef T type; }; template struct RemovePointer { typedef T type; }; /* add pointer */ template struct AddPointer { typedef typename RemoveReference::type *type; }; /* add lvalue reference */ template struct AddLvalueReference { typedef T &type; }; template struct AddLvalueReference { typedef T &type; }; template struct AddLvalueReference { typedef T &type; }; template<> struct AddLvalueReference { typedef void type; }; template<> struct AddLvalueReference { typedef const void type; }; template<> struct AddLvalueReference { typedef volatile void type; }; template<> struct AddLvalueReference { typedef const volatile void type; }; /* add rvalue reference */ template using AddRvalueReference = internal::AddRvalueReference; /* remove extent */ template struct RemoveExtent { typedef T type; }; template struct RemoveExtent { typedef T type; }; template struct RemoveExtent { typedef T type; }; /* remove all extents */ template struct RemoveAllExtents { typedef T type; }; template struct RemoveAllExtents { typedef typename RemoveAllExtents::type type; }; template struct RemoveAllExtents { typedef typename RemoveAllExtents::type type; }; /* make (un)signed * * this is bad, but i don't see any better way * shamelessly copied from graphitemaster @ neothyne */ namespace internal { template struct TypeList { typedef T first; typedef U rest; }; /* not a type */ struct NAT { NAT() = delete; NAT(const NAT &) = delete; NAT &operator=(const NAT &) = delete; ~NAT() = delete; }; typedef TypeList>>>> stypes; typedef TypeList>>>> utypes; template struct TypeFindFirst; template struct TypeFindFirst, N, true> { typedef T type; }; template struct TypeFindFirst, N, false> { typedef typename TypeFindFirst::type type; }; template::type>::value, bool = IsVolatile::type>::value > struct ApplyConstVolatile { typedef U type; }; template struct ApplyConstVolatile { /* const */ typedef const U type; }; template struct ApplyConstVolatile { /* volatile */ typedef volatile U type; }; template struct ApplyConstVolatile { /* const volatile */ typedef const volatile U type; }; template struct ApplyConstVolatile { /* const */ typedef const U &type; }; template struct ApplyConstVolatile { /* volatile */ typedef volatile U &type; }; template struct ApplyConstVolatile { /* const volatile */ typedef const volatile U &type; }; template::value || IsEnum::value> struct MakeSigned {}; template::value || IsEnum::value> struct MakeUnsigned {}; template struct MakeSigned { typedef typename TypeFindFirst::type type; }; template struct MakeUnsigned { typedef typename TypeFindFirst::type type; }; template<> struct MakeSigned {}; template<> struct MakeSigned { typedef schar type; }; template<> struct MakeSigned { typedef schar type; }; template<> struct MakeSigned { typedef short type; }; template<> struct MakeSigned { typedef short type; }; template<> struct MakeSigned { typedef int type; }; template<> struct MakeSigned { typedef int type; }; template<> struct MakeSigned { typedef long type; }; template<> struct MakeSigned { typedef long type; }; template<> struct MakeSigned { typedef llong type; }; template<> struct MakeSigned { typedef llong type; }; template<> struct MakeUnsigned {}; template<> struct MakeUnsigned { typedef uchar type; }; template<> struct MakeUnsigned { typedef uchar type; }; template<> struct MakeUnsigned { typedef ushort type; }; template<> struct MakeUnsigned { typedef ushort type; }; template<> struct MakeUnsigned { typedef uint type; }; template<> struct MakeUnsigned { typedef uint type; }; template<> struct MakeUnsigned { typedef ulong type; }; template<> struct MakeUnsigned { typedef ulong type; }; template<> struct MakeUnsigned { typedef ullong type; }; template<> struct MakeUnsigned { typedef ullong type; }; } template struct MakeSigned { typedef typename internal::ApplyConstVolatile::type >::type >::type type; }; template struct MakeUnsigned { typedef typename internal::ApplyConstVolatile::type >::type >::type type; }; /* common type */ /* conditional */ template struct Conditional { typedef T type; }; template struct Conditional { typedef U type; }; /* result of call at compile time */ namespace internal { template inline auto result_of_invoke(F &&f, A &&...args) -> decltype(forward(f)(forward(args)...)) { return forward(f)(forward(args)...); } template inline auto result_of_invoke(T B::*pmd, D &&ref) -> decltype(forward(ref).*pmd) { return forward(ref).*pmd; } template inline auto result_of_invoke(PMD &&pmd, P &&ptr) -> decltype((*forward

(ptr)).*forward(pmd)) { return (*forward

(ptr)).*forward(pmd); } template inline auto result_of_invoke(T B::*pmf, D &&ref, A &&...args) -> decltype((forward(ref).*pmf)(forward(args)...)) { return (forward(ref).*pmf)(forward(args)...); } template inline auto result_of_invoke(PMF &&pmf, P &&ptr, A &&...args) -> decltype(((*forward

(ptr)).*forward(pmf))(forward(args)...)) { return ((*forward

(ptr)).*forward(pmf))(forward(args)...); } template struct ResultOf {}; template struct ResultOf(), declval()...)))> { using type = decltype(result_of_invoke(declval(), declval()...)); }; } template struct ResultOf: internal::ResultOf {}; /* enable_if */ template struct enable_if {}; template struct enable_if { typedef T type; }; /* decay */ template struct Decay { private: typedef typename RemoveReference::type U; public: typedef typename Conditional::value, typename RemoveExtent::type *, typename Conditional::value, typename AddPointer::type, typename RemoveConstVolatile::type >::type >::type type; }; /* common type */ template struct CommonType; template struct CommonType { typedef Decay type; }; template struct CommonType { typedef Decay() : declval())> type; }; template struct CommonType { typedef typename CommonType::type, V...>::type type; }; /* aligned storage */ namespace internal { template struct AlignedStorageTest { union type { uchar data[N]; octa::max_align_t align; }; }; }; template::type) > struct AlignedStorage { struct type { alignas(A) uchar data[N]; }; }; /* aligned union */ namespace internal { template struct AlignMax; template struct AlignMax { static constexpr size_t value = N; }; template struct AlignMax { static constexpr size_t value = (N1 > N2) ? N1 : N2; }; template struct AlignMax { static constexpr size_t value = AlignMax::value, N...>::value; }; } template struct AlignedUnion { static constexpr size_t alignment_value = internal::AlignMax::value; struct type { alignas(alignment_value) uchar data[internal::AlignMax::value]; }; }; /* underlying type */ template::value> struct UnderlyingTypeBase; template struct UnderlyingTypeBase { typedef typename Conditional::value, typename MakeSigned::type, typename MakeUnsigned::type >::type type; }; template struct UnderlyingType { typedef typename UnderlyingTypeBase::type type; }; } #endif