/* 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" namespace octa { /* forward declarations */ template struct RemoveCV; template struct AddLvalueReference; template struct AddConst; template struct IsReference; template struct RemoveAllExtents; template struct IsTriviallyDefaultConstructible; template struct CommonType; /* 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 __OctaIsVoid : false_t {}; template< > struct __OctaIsVoid: true_t {}; template struct IsVoid: __OctaIsVoid::type> {}; /* is null pointer */ template struct __OctaIsNullPointer : false_t {}; template< > struct __OctaIsNullPointer: true_t {}; template struct IsNullPointer: __OctaIsNullPointer< typename RemoveCV::type > {}; /* is integer */ template struct __OctaIsIntegral: false_t {}; template<> struct __OctaIsIntegral: true_t {}; template<> struct __OctaIsIntegral: true_t {}; template<> struct __OctaIsIntegral: true_t {}; template<> struct __OctaIsIntegral: true_t {}; template<> struct __OctaIsIntegral: true_t {}; template<> struct __OctaIsIntegral: true_t {}; template<> struct __OctaIsIntegral: true_t {}; template<> struct __OctaIsIntegral: true_t {}; template<> struct __OctaIsIntegral: true_t {}; template<> struct __OctaIsIntegral: true_t {}; template<> struct __OctaIsIntegral: true_t {}; template<> struct __OctaIsIntegral: true_t {}; template struct IsIntegral: __OctaIsIntegral::type> {}; /* is floating point */ template struct __OctaIsFloatingPoint: false_t {}; template<> struct __OctaIsFloatingPoint: true_t {}; template<> struct __OctaIsFloatingPoint: true_t {}; template<> struct __OctaIsFloatingPoint: true_t {}; template struct IsFloatingPoint: __OctaIsFloatingPoint::type> {}; /* is array */ template struct IsArray : false_t {}; template struct IsArray: true_t {}; template struct IsArray: true_t {}; /* is pointer */ template struct __OctaIsPointer : false_t {}; template struct __OctaIsPointer: true_t {}; template struct IsPointer: __OctaIsPointer::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 */ 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::value || IsVoid::value || IsReference::value || IsNullPointer::value > struct __OctaIsFunction: IntegralConstant(__octa_function_source(0))) == 1 > {}; template struct __OctaIsFunction: false_t {}; template struct IsFunction: __OctaIsFunction {}; /* 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 __OctaIsMemberPointer: false_t {}; template struct __OctaIsMemberPointer: true_t {}; template struct IsMemberPointer: __OctaIsMemberPointer< typename RemoveCV::type > {}; /* is pointer to member object */ template struct __OctaIsMemberObjectPointer: false_t {}; template struct __OctaIsMemberObjectPointer: IntegralConstant::value > {}; template struct IsMemberObjectPointer: __OctaIsMemberObjectPointer::type> {}; /* is pointer to member function */ template struct __OctaIsMemberFunctionPointer: false_t {}; template struct __OctaIsMemberFunctionPointer: IntegralConstant::value > {}; template struct IsMemberFunctionPointer: __OctaIsMemberFunctionPointer::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 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 IsTrivial: IntegralConstant::value && IsTriviallyDefaultConstructible::value) > {}; /* has virtual destructor */ template struct HasVirtualDestructor: IntegralConstant {}; /* is constructible */ template struct __OctaSelect2nd { typedef T type; }; struct __OctaAny { __OctaAny(...); }; template typename __OctaSelect2nd< decltype(octa::move(T(octa::declval()...))), true_t >::type __octa_is_ctible_test(T &&, A &&...); template false_t __octa_is_ctible_test(__OctaAny, A &&...); template struct __OctaCtibleCore: CommonType< decltype(__octa_is_ctible_test(octa::declval(), octa::declval()...)) >::type {}; /* function types are not constructible */ template struct __OctaCtibleCore: false_t {}; /* scalars are default constructible, refs are not */ template struct __OctaCtibleCore: IsScalar {}; /* scalars and references are constructible from one arg if * implicitly convertible to scalar or reference */ template struct __OctaCtibleRef { static true_t test(T); static false_t test(...); }; template struct __OctaCtibleCore: CommonType< decltype(__OctaCtibleRef::test(octa::declval())) >::type {}; /* scalars and references are not constructible from multiple args */ template struct __OctaCtibleCore: false_t {}; /* treat scalars and refs separately */ template struct __OctaCtibleVoidCheck: __OctaCtibleCore< (IsScalar::value || IsReference::value), T, A... > {}; /* if any of T or A is void, IsConstructible should be false */ template struct __OctaCtibleVoidCheck: false_t {}; template struct __OctaCtibleContainsVoid; template<> struct __OctaCtibleContainsVoid<>: false_t {}; template struct __OctaCtibleContainsVoid { static constexpr bool value = IsVoid::value || __OctaCtibleContainsVoid::value; }; /* entry point */ template struct __OctaCtible: __OctaCtibleVoidCheck< __OctaCtibleContainsVoid::value || IsAbstract::value, T, A... > {}; /* array types are default constructible if their element type is */ template struct __OctaCtibleCore: __OctaCtible< typename RemoveAllExtents::type > {}; /* otherwise array types are not constructible by this syntax */ template struct __OctaCtibleCore: false_t {}; /* incomplete array types are not constructible */ template struct __OctaCtibleCore: false_t {}; template struct IsConstructible: __OctaCtible {}; /* is default constructible */ template struct IsDefaultConstructible: IsConstructible {}; /* is copy constructible */ template struct IsCopyConstructible: IsConstructible::type>::type > {}; /* is move constructible */ template struct IsMoveConstructible: IsConstructible::type > {}; /* is assignable */ template typename __OctaSelect2nd< decltype((octa::declval() = octa::declval())), true_t >::type __octa_assign_test(T &&, U &&); template false_t __octa_assign_test(__OctaAny, T &&); template::value || IsVoid::value> struct __OctaIsAssignable: CommonType< decltype(__octa_assign_test(octa::declval(), octa::declval())) >::type {}; template struct __OctaIsAssignable: false_t {}; template struct IsAssignable: __OctaIsAssignable {}; /* is copy assignable */ template struct IsCopyAssignable: IsAssignable< typename AddLvalueReference::type, typename AddLvalueReference::type>::type > {}; /* is move assignable */ template struct IsMoveAssignable: IsAssignable< typename AddLvalueReference::type, const typename internal::AddRvalueReference::type > {}; /* is destructible */ template struct __OctaIsDtibleApply { typedef int type; }; template struct IsDestructorWellformed { template static char test(typename __OctaIsDtibleApply< decltype(octa::declval().~TT()) >::type); template static int test(...); static constexpr bool value = (sizeof(test(12)) == sizeof(char)); }; template struct __OctaDtibleImpl; template struct __OctaDtibleImpl: IntegralConstant::type>::value > {}; template struct __OctaDtibleImpl: true_t {}; template struct __OctaDtibleFalse; template struct __OctaDtibleFalse : __OctaDtibleImpl::value> {}; template struct __OctaDtibleFalse: false_t {}; template struct IsDestructible: __OctaDtibleFalse::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 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 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 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 IsNothrowCopyAssignable: IsNothrowAssignable::type > {}; /* is nothrow move assignable */ template struct IsNothrowMoveAssignable: IsNothrowAssignable::type > {}; /* is nothrow destructible */ template struct __OctaIsNothrowDtible; template struct __OctaIsNothrowDtible: IntegralConstant().~T()) > {}; template struct IsNothrowDestructible: __OctaIsNothrowDtible::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 __OctaIsConvertible { typedef typename IsVoid::type type; }; template struct __OctaIsConvertible { template static void test_f(TT); template(octa::declval())) > static true_t test(int); template static false_t test(...); typedef decltype(test(0)) type; }; template struct IsConvertible: __OctaIsConvertible::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 RemoveCV { typedef typename RemoveVolatile::type>::type type; }; /* add const, volatile, cv */ template::value || IsFunction::value || IsConst::value> struct __OctaAddConst { typedef T type; }; template struct __OctaAddConst { typedef const T type; }; template struct AddConst { typedef typename __OctaAddConst::type type; }; template::value || IsFunction::value || IsVolatile::value> struct __OctaAddVolatile { typedef T type; }; template struct __OctaAddVolatile { typedef volatile T type; }; template struct AddVolatile { typedef typename __OctaAddVolatile::type type; }; template struct AddCV { 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 */ 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>>>> stypes; typedef __OctaTL>>>> utypes; template struct __OctaTypeFindFirst; template struct __OctaTypeFindFirst<__OctaTL, N, true> { typedef T type; }; template struct __OctaTypeFindFirst<__OctaTL, N, false> { typedef typename __OctaTypeFindFirst::type type; }; template::type>::value, bool = IsVolatile::type>::value > struct __OctaApplyCV { typedef U type; }; template struct __OctaApplyCV { /* const */ typedef const U type; }; template struct __OctaApplyCV { /* volatile */ typedef volatile U type; }; template struct __OctaApplyCV { /* const volatile */ typedef const volatile U type; }; template struct __OctaApplyCV { /* const */ typedef const U &type; }; template struct __OctaApplyCV { /* volatile */ typedef volatile U &type; }; template struct __OctaApplyCV { /* const volatile */ typedef const volatile U &type; }; template::value || IsEnum::value> struct __OctaMakeSigned {}; template::value || IsEnum::value> struct __OctaMakeUnsigned {}; template struct __OctaMakeSigned { typedef typename __OctaTypeFindFirst::type type; }; template struct __OctaMakeUnsigned { typedef typename __OctaTypeFindFirst::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 MakeSigned { typedef typename __OctaApplyCV::type >::type >::type type; }; template struct MakeUnsigned { typedef typename __OctaApplyCV::type >::type >::type type; }; /* conditional */ template struct Conditional { typedef T type; }; template struct Conditional { typedef U type; }; /* result of call at compile time */ template inline auto __octa_rof_invoke(F &&f, A &&...args) -> decltype(forward(f)(forward(args)...)) { return forward(f)(forward(args)...); } template inline auto __octa_rof_invoke(T B::*pmd, D &&ref) -> decltype(forward(ref).*pmd) { return forward(ref).*pmd; } template inline auto __octa_rof_invoke(PMD &&pmd, P &&ptr) -> decltype((*forward

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

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

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

(ptr)).*forward(pmf))(forward(args)...); } template struct __OctaResultOf {}; template struct __OctaResultOf(), octa::declval()...)))> { using type = decltype(__octa_rof_invoke(octa::declval(), octa::declval()...)); }; template struct ResultOf: __OctaResultOf {}; /* enable if */ template struct EnableIf {}; template struct EnableIf { 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 RemoveCV::type >::type >::type type; }; /* common type */ template struct CommonType; template struct CommonType { typedef Decay type; }; template struct CommonType { typedef Decay() : octa::declval())> type; }; template struct CommonType { typedef typename CommonType::type, V...>::type type; }; /* aligned storage */ template struct __OctaAlignedTest { union type { uchar data[N]; octa::max_align_t align; }; }; template::type) > struct AlignedStorage { struct type { alignas(A) uchar data[N]; }; }; /* aligned union */ template struct __OctaAlignMax; template struct __OctaAlignMax { static constexpr size_t value = N; }; template struct __OctaAlignMax { static constexpr size_t value = (N1 > N2) ? N1 : N2; }; template struct __OctaAlignMax { static constexpr size_t value = __OctaAlignMax<__OctaAlignMax::value, N...>::value; }; template struct AlignedUnion { static constexpr size_t alignment_value = __OctaAlignMax::value; struct type { alignas(alignment_value) uchar data[__OctaAlignMax::value]; }; }; /* underlying type */ template::value> struct __OctaUnderlyingType; template struct __OctaUnderlyingType { typedef typename Conditional::value, typename MakeSigned::type, typename MakeUnsigned::type >::type type; }; template struct UnderlyingType { typedef typename __OctaUnderlyingType::type type; }; } #endif