/* 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 { /* conditional */ template struct Conditional { typedef T type; }; template struct Conditional { typedef U type; }; /* removers */ template using RemoveReference = internal::RemoveReference; 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; }; /* integral constant */ template struct IntegralConstant { static constexpr const 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 const T IntegralConstant::value; /* is integer */ template struct IsIntegerBase: false_t {}; template<> struct IsIntegerBase: true_t {}; template<> struct IsIntegerBase: true_t {}; template<> struct IsIntegerBase: true_t {}; template<> struct IsIntegerBase: true_t {}; template<> struct IsIntegerBase: true_t {}; template<> struct IsIntegerBase: true_t {}; template<> struct IsIntegerBase: true_t {}; template<> struct IsIntegerBase: true_t {}; template<> struct IsIntegerBase: true_t {}; template<> struct IsIntegerBase: true_t {}; template<> struct IsIntegerBase: true_t {}; template<> struct IsIntegerBase: true_t {}; template struct IsInteger: IsIntegerBase::type> {}; /* is floating point */ template struct IsFloatBase : false_t {}; template<> struct IsFloatBase: true_t {}; template<> struct IsFloatBase: true_t {}; template<> struct IsFloatBase: true_t {}; template struct IsFloat: IsFloatBase::type> {}; /* is number */ template struct IsNumber: IntegralConstant::value || IsFloat::value) > {}; /* is pointer */ template struct IsPointerBase : false_t {}; template struct IsPointerBase: true_t {}; template struct IsPointer: IsPointerBase::type> {}; /* is pointer to member function */ template struct IsMemberPointerBase: false_t {}; template struct IsMemberPointerBase: true_t {}; template struct IsMemberPointer: IsMemberPointerBase< typename RemoveConstVolatile::type > {}; /* is null pointer */ template struct IsNullPointerBase : false_t {}; template< > struct IsNullPointerBase: true_t {}; template struct IsNullPointer: IsNullPointerBase< typename RemoveConstVolatile::type > {}; /* is POD: currently wrong */ template struct IsPOD: IntegralConstant::value || IsFloat::value || IsPointer::value) > {}; /* is class */ struct IsClassBase { template static char test(void (T::*)(void)); template static int test(...); }; template struct IsClass: IntegralConstant(0)) == 1 > {}; /* type equality */ template struct IsEqual : false_t {}; template struct IsEqual: true_t {}; /* 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 reference */ template struct IsReference: IntegralConstant::value || IsRvalueReference::value) > {}; /* 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; /* is array */ template struct IsArray : false_t {}; template struct IsArray: true_t {}; template struct IsArray: true_t {}; /* 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(internal::result_of_invoke(declval(), declval()...)); }; } /* cppreference.com used for reference */ template struct ResultOf: internal::ResultOf {}; } #endif