/* Type traits for OctaSTD. * * This file is part of OctaSTD. See COPYING.md for futher information. * Portions of this file are originally adapted from the libc++ project. */ #ifndef OSTD_TYPE_TRAITS_HH #define OSTD_TYPE_TRAITS_HH #include #include #include #include "ostd/types.hh" namespace ostd { /* forward declarations */ namespace detail { template struct RemoveCvBase; template struct AddLr; template struct AddRr; template struct AddConstBase; template struct RemoveReferenceBase; template struct RemoveAllExtentsBase; template struct CommonTypeBase; } template using RemoveCv = typename detail::RemoveCvBase::Type; template using AddLvalueReference = typename detail::AddLr::Type; template using AddRvalueReference = typename detail::AddRr::Type; template using AddConst = typename detail::AddConstBase::Type; template using RemoveReference = typename detail::RemoveReferenceBase::Type; template using RemoveAllExtents = typename detail::RemoveAllExtentsBase::Type; /* size in bits */ template constexpr size_t SizeInBits = sizeof(T) * CHAR_BIT; /* integral constant */ template struct Constant { static constexpr T value = val; using Value = T; using Type = Constant; constexpr operator Value() const { return value; } constexpr Value operator()() const { return value; } }; template using BoolConstant = Constant; using True = BoolConstant; using False = BoolConstant; template constexpr T Constant::value; /* type equality */ template constexpr bool IsSame = false; template constexpr bool IsSame = true; /* is void */ template constexpr bool IsVoid = IsSame, void>; /* is null pointer */ template constexpr bool IsNullPointer = IsSame, std::nullptr_t>; /* is integer */ template constexpr bool IsIntegral = std::is_integral_v; /* is floating point */ template constexpr bool IsFloatingPoint = std::is_floating_point_v; /* is array */ template constexpr bool IsArray = false; template constexpr bool IsArray = true; template constexpr bool IsArray = true; /* is pointer */ namespace detail { template constexpr bool IsPointerBase = false; template constexpr bool IsPointerBase = true; } template constexpr bool IsPointer = detail::IsPointerBase>; /* is lvalue reference */ template constexpr bool IsLvalueReference = false; template constexpr bool IsLvalueReference = true; /* is rvalue reference */ template constexpr bool IsRvalueReference = false; template constexpr bool IsRvalueReference = true; /* is reference */ template constexpr bool IsReference = IsLvalueReference || IsRvalueReference; /* is enum */ template constexpr bool IsEnum = __is_enum(T); /* is union */ template constexpr bool IsUnion = __is_union(T); /* is class */ template constexpr bool IsClass = __is_class(T); /* is function */ namespace detail { 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< typename T, bool = IsClass || IsUnion || IsVoid || IsReference || IsNullPointer > constexpr bool IsFunctionBase = sizeof(function_test(function_source(0))) == 1; template constexpr bool IsFunctionBase = false; } /* namespace detail */ template constexpr bool IsFunction = detail::IsFunctionBase; /* is arithmetic */ template constexpr bool IsArithmetic = IsIntegral || IsFloatingPoint; /* is fundamental */ template constexpr bool IsFundamental = IsArithmetic || IsVoid || IsNullPointer; /* is compound */ template constexpr bool IsCompound = !IsFundamental; /* is pointer to member */ namespace detail { template constexpr bool IsMemberPointerBase = false; template constexpr bool IsMemberPointerBase = true; } template constexpr bool IsMemberPointer = detail::IsMemberPointerBase>; /* is pointer to member object */ namespace detail { template constexpr bool IsMemberObjectPointerBase = false; template constexpr bool IsMemberObjectPointerBase = !IsFunction; } template constexpr bool IsMemberObjectPointer = detail::IsMemberObjectPointerBase>; /* is pointer to member function */ namespace detail { template constexpr bool IsMemberFunctionPointerBase = false; template constexpr bool IsMemberFunctionPointerBase = IsFunction; } template constexpr bool IsMemberFunctionPointer = detail::IsMemberFunctionPointerBase>; /* internal member traits, from libc++ */ namespace detail { template struct MemberPointerTraitsBase {}; template struct MemberPointerTraitsBase { using Class = C; using Result = R; using Func = R(A...); }; template struct MemberPointerTraitsBase { using Class = C; using Result = R; using Func = R(A..., ...); }; template struct MemberPointerTraitsBase { using Class = C const; using Result = R; using Func = R(A...); }; template struct MemberPointerTraitsBase { using Class = C const; using Result = R; using Func = R(A..., ...); }; template struct MemberPointerTraitsBase { using Class = C volatile; using Result = R; using Func = R(A...); }; template struct MemberPointerTraitsBase { using Class = C volatile; using Result = R; using Func = R(A..., ...); }; template struct MemberPointerTraitsBase { using Class = C const volatile; using Result = R; using Func = R(A...); }; template struct MemberPointerTraitsBase< R (C::*)(A..., ...) const volatile, true, false > { using Class = C const volatile; using Result = R; using Func = R(A..., ...); }; template struct MemberPointerTraitsBase { using Class = C &; using Result = R; using Func = R(A...); }; template struct MemberPointerTraitsBase { using Class = C &; using Result = R; using Func = R(A..., ...); }; template struct MemberPointerTraitsBase { using Class = C const &; using Result = R; using Func = R(A...); }; template struct MemberPointerTraitsBase { using Class = C const &; using Result = R; using Func = R(A..., ...); }; template struct MemberPointerTraitsBase { using Class = C volatile &; using Result = R; using Func = R(A...); }; template struct MemberPointerTraitsBase< R (C::*)(A..., ...) volatile &, true, false > { using Class = C volatile &; using Result = R; using Func = R(A..., ...); }; template struct MemberPointerTraitsBase< R (C::*)(A...) const volatile &, true, false > { using Class = C const volatile &; using Result = R; using Func = R(A...); }; template struct MemberPointerTraitsBase< R (C::*)(A..., ...) const volatile &, true, false > { using Class = C const volatile &; using Result = R; using Func = R(A..., ...); }; template struct MemberPointerTraitsBase { using Class = C &&; using Result = R; using Func = R(A...); }; template struct MemberPointerTraitsBase { using Class = C &&; using Result = R; using Func = R(A..., ...); }; template struct MemberPointerTraitsBase { using Class = C const &&; using Result = R; using Func = R(A...); }; template struct MemberPointerTraitsBase { using Class = C const &&; using Result = R; using Func = R(A..., ...); }; template struct MemberPointerTraitsBase { using Class = C volatile &&; using Result = R; using Func = R(A...); }; template struct MemberPointerTraitsBase< R (C::*)(A..., ...) volatile &&, true, false > { using Class = C volatile &&; using Result = R; using Func = R(A..., ...); }; template struct MemberPointerTraitsBase< R (C::*)(A...) const volatile &&, true, false > { using Class = C const volatile &&; using Result = R; using Func = R(A...); }; template struct MemberPointerTraitsBase< R (C::*)(A..., ...) const volatile &&, true, false > { using Class = C const volatile &&; using Result = R; using Func = R(A..., ...); }; template struct MemberPointerTraitsBase { using Class = C; using Result = R; }; template using MemberPointerClass = typename MemberPointerTraitsBase< RemoveCv, IsMemberFunctionPointer, IsMemberObjectPointer >::Class; template using MemberPointerResult = typename MemberPointerTraitsBase< RemoveCv, IsMemberFunctionPointer, IsMemberObjectPointer >::Result; template using MemberPointerFunc = typename MemberPointerTraitsBase< RemoveCv, IsMemberFunctionPointer, IsMemberObjectPointer >::Func; } /* namespace detail */ /* is object */ template constexpr bool IsObject = !IsFunction && !IsVoid && !IsReference; /* is scalar */ template constexpr bool IsScalar = IsMemberPointer || IsPointer || IsEnum || IsNullPointer || IsArithmetic; /* is abstract */ template constexpr bool IsAbstract = __is_abstract(T); /* is const */ template constexpr bool IsConst = IsSame; /* is volatile */ template constexpr bool IsVolatile = IsSame; /* is empty */ template constexpr bool IsEmpty = __is_empty(T); /* is POD */ template constexpr bool IsPod = __is_pod(T); /* is polymorphic */ template constexpr bool IsPolymorphic = __is_polymorphic(T); /* is signed */ namespace detail { template constexpr bool IsSignedCore = T(-1) < T(0); template> constexpr bool IsSignedBase = false; template constexpr bool IsSignedBase = detail::IsSignedCore; } template constexpr bool IsSigned = detail::IsSignedBase; /* is unsigned */ namespace detail { template constexpr bool IsUnsignedCore = T(0) < T(-1); template> constexpr bool IsUnsignedBase = false; template constexpr bool IsUnsignedBase = detail::IsUnsignedCore; } template constexpr bool IsUnsigned = detail::IsUnsignedBase; /* is standard layout */ template constexpr bool IsStandardLayout = __is_standard_layout(T); /* is literal type */ template constexpr bool IsLiteralType = __is_literal_type(T); /* is trivially copyable */ template constexpr bool IsTriviallyCopyable = IsScalar>; /* is trivial */ template constexpr bool IsTrivial = __is_trivial(T); /* has virtual destructor */ template constexpr bool HasVirtualDestructor = __has_virtual_destructor(T); /* is constructible */ namespace detail { template struct Select2nd { using Type = T; }; struct Any { Any(...); }; template typename Select2nd< decltype(std::move(T(std::declval()...))), True >::Type is_ctible_test(T &&, A &&...); template False is_ctible_test(Any, A &&...); template constexpr bool CtibleCore = CommonTypeBase< decltype(is_ctible_test(std::declval(), std::declval()...)) >::Type::value; /* function types are not constructible */ template constexpr bool CtibleCore = false; /* scalars are default constructible, refs are not */ template constexpr bool CtibleCore = IsScalar; /* scalars and references are constructible from one arg if * implicitly convertible to scalar or reference */ template struct CtibleRef { static True test(T); static False test(...); }; template constexpr bool CtibleCore = CommonTypeBase< decltype(CtibleRef::test(std::declval())) >::Type::value; /* scalars and references are not constructible from multiple args */ template constexpr bool CtibleCore = false; /* treat scalars and refs separately */ template constexpr bool CtibleVoidCheck = CtibleCore<(IsScalar || IsReference), T, A...>; /* if any of T or A is void, IsConstructible should be false */ template constexpr bool CtibleVoidCheck = false; template constexpr bool CtibleContainsVoid = false; template<> constexpr bool CtibleContainsVoid<> = false; template constexpr bool CtibleContainsVoid = IsVoid || CtibleContainsVoid; /* entry point */ template constexpr bool Ctible = CtibleVoidCheck || IsAbstract, T, A...>; /* array types are default constructible if their element type is */ template constexpr bool CtibleCore = Ctible>; /* otherwise array types are not constructible by this syntax */ template constexpr bool CtibleCore = false; /* incomplete array types are not constructible */ template constexpr bool CtibleCore = false; } /* namespace detail */ template constexpr bool IsConstructible = detail::Ctible; /* is default constructible */ template constexpr bool IsDefaultConstructible = IsConstructible; /* is copy constructible */ template constexpr bool IsCopyConstructible = IsConstructible>>; /* is move constructible */ template constexpr bool IsMoveConstructible = IsConstructible>; /* is nothrow constructible */ namespace detail { template constexpr bool NothrowCtibleCore = false; template constexpr bool NothrowCtibleCore = noexcept(T(std::declval()...)); template void implicit_conv_to(T) noexcept {} template constexpr bool NothrowCtibleCore = noexcept(ostd::detail::implicit_conv_to(std::declval())); template constexpr bool NothrowCtibleCore = false; } /* namespace detail */ template constexpr bool IsNothrowConstructible = detail::NothrowCtibleCore, IsReference, T, A...>; template constexpr bool IsNothrowConstructible = detail::NothrowCtibleCore, IsReference, T>; /* is nothrow default constructible */ template constexpr bool IsNothrowDefaultConstructible = IsNothrowConstructible; /* is nothrow copy constructible */ template constexpr bool IsNothrowCopyConstructible = IsNothrowConstructible>>; /* is nothrow move constructible */ template constexpr bool IsNothrowMoveConstructible = IsNothrowConstructible>; /* is assignable */ namespace detail { template typename detail::Select2nd< decltype((std::declval() = std::declval())), True >::Type assign_test(T &&, U &&); template False assign_test(Any, T &&); template || IsVoid> constexpr bool IsAssignableBase = CommonTypeBase< decltype(assign_test(std::declval(), std::declval())) >::Type::value; template constexpr bool IsAssignableBase = false; } /* namespace detail */ template constexpr bool IsAssignable = detail::IsAssignableBase; /* is copy assignable */ template constexpr bool IsCopyAssignable = IsAssignable, AddLvalueReference>>; /* is move assignable */ template constexpr bool IsMoveAssignable = IsAssignable, AddRvalueReference const>; /* is nothrow assignable */ namespace detail { template constexpr bool NothrowAssignableCore = false; template constexpr bool NothrowAssignableCore = false; template constexpr bool NothrowAssignableCore = noexcept(std::declval() = std::declval()); } template constexpr bool IsNothrowAssignable = detail::NothrowAssignableCore, T, A>; /* is nothrow copy assignable */ template constexpr bool IsNothrowCopyAssignable = IsNothrowAssignable, AddLvalueReference>>; /* is nothrow move assignable */ template constexpr bool IsNothrowMoveAssignable = IsNothrowAssignable, AddRvalueReference>; /* is destructible */ namespace detail { template struct IsDtibleApply { using Type = int; }; template struct IsDestructorWellformed { template static char test(typename IsDtibleApply< decltype(std::declval().~TT()) >::Type); template static int test(...); static constexpr bool value = (sizeof(test(12)) == sizeof(char)); }; template constexpr bool DtibleImpl = false; template constexpr bool DtibleImpl = IsDestructorWellformed>::value; template constexpr bool DtibleImpl = true; template constexpr bool DtibleFalse = false; template constexpr bool DtibleFalse = DtibleImpl>; template constexpr bool DtibleFalse = false; template constexpr bool IsDestructibleBase = detail::DtibleFalse>; template constexpr bool IsDestructibleBase = false; template<> constexpr bool IsDestructibleBase = false; } /* namespace detail */ template constexpr bool IsDestructible = detail::IsDestructibleBase; /* is nothrow destructible */ namespace detail { template constexpr bool NothrowDtibleCore = false; template constexpr bool NothrowDtibleCore = false; template constexpr bool NothrowDtibleCore = noexcept(std::declval().~T()); } template constexpr bool IsNothrowDestructible = detail::NothrowDtibleCore, T>; template constexpr bool IsNothrowDestructible = IsNothrowDestructible; /* is trivially constructible */ namespace detail { template constexpr bool IsTriviallyConstructibleBase = false; template constexpr bool IsTriviallyConstructibleBase = __has_trivial_constructor(T); template constexpr bool IsTriviallyConstructibleBase = __has_trivial_copy(T); template constexpr bool IsTriviallyConstructibleBase = __has_trivial_copy(T); template constexpr bool IsTriviallyConstructibleBase = __has_trivial_copy(T); } /* namespace detail */ template constexpr bool IsTriviallyConstructible = detail::IsTriviallyConstructibleBase; /* is trivially default constructible */ template constexpr bool IsTriviallyDefaultConstructible = IsTriviallyConstructible; /* is trivially copy constructible */ template constexpr bool IsTriviallyCopyConstructible = IsTriviallyConstructible>; /* is trivially move constructible */ template constexpr bool IsTriviallyMoveConstructible = IsTriviallyConstructible>; /* is trivially assignable */ namespace detail { template constexpr bool IsTriviallyAssignableBase = false; template constexpr bool IsTriviallyAssignableBase = __has_trivial_assign(T); template constexpr bool IsTriviallyAssignableBase = __has_trivial_copy(T); template constexpr bool IsTriviallyAssignableBase = __has_trivial_copy(T); template constexpr bool IsTriviallyAssignableBase = __has_trivial_copy(T); } /* namespace detail */ template constexpr bool IsTriviallyAssignable = detail::IsTriviallyAssignableBase; /* is trivially copy assignable */ template constexpr bool IsTriviallyCopyAssignable = IsTriviallyAssignable>; /* is trivially move assignable */ template constexpr bool IsTriviallyMoveAssignable = IsTriviallyAssignable>; /* is trivially destructible */ template constexpr bool IsTriviallyDestructible = __has_trivial_destructor(T); /* is base of */ template constexpr bool IsBaseOf = __is_base_of(B, D); /* is convertible */ namespace detail { template< typename F, typename T, bool = IsVoid || IsFunction || IsArray > struct IsConvertibleBase { static constexpr bool value = IsVoid; }; template struct IsConvertibleBase { template static void test_f(TT); template(std::declval())) > static True test(int); template static False test(...); static constexpr bool value = decltype(test(0))::value; }; } template constexpr bool IsConvertible = detail::IsConvertibleBase::value; /* extent */ namespace detail { template constexpr size_t ExtentBase = 0; template constexpr size_t ExtentBase = 0; template constexpr size_t ExtentBase = detail::ExtentBase; template constexpr size_t ExtentBase = N; template constexpr size_t ExtentBase = detail::ExtentBase; } /* namespace detail */ template constexpr size_t Extent = detail::ExtentBase; /* rank */ namespace detail { template constexpr size_t RankBase = 0; template constexpr size_t RankBase = detail::RankBase + 1; template constexpr size_t RankBase = detail::RankBase + 1; } template constexpr size_t Rank = detail::RankBase; /* remove const, volatile, cv */ namespace detail { template struct RemoveConstBase { using Type = T; }; template struct RemoveConstBase { using Type = T; }; template struct RemoveVolatileBase { using Type = T; }; template struct RemoveVolatileBase { using Type = T; }; } template using RemoveConst = typename detail::RemoveConstBase::Type; template using RemoveVolatile = typename detail::RemoveVolatileBase::Type; namespace detail { template struct RemoveCvBase { using Type = RemoveVolatile>; }; } /* add const, volatile, cv */ namespace detail { template || IsFunction || IsConst> struct AddConstCore { using Type = T; }; template struct AddConstCore { using Type = T const; }; template struct AddConstBase { using Type = typename AddConstCore::Type; }; template || IsFunction || IsVolatile> struct AddVolatileCore { using Type = T; }; template struct AddVolatileCore { using Type = T volatile; }; template struct AddVolatileBase { using Type = typename AddVolatileCore::Type; }; } template using AddVolatile = typename detail::AddVolatileBase::Type; namespace detail { template struct AddCvBase { using Type = AddConst>; }; } template using AddCv = typename detail::AddCvBase::Type; /* remove reference */ namespace detail { template struct RemoveReferenceBase { using Type = T; }; template struct RemoveReferenceBase { using Type = T; }; template struct RemoveReferenceBase { using Type = T; }; } /* remove pointer */ namespace detail { template struct RemovePointerBase { using Type = T; }; template struct RemovePointerBase { using Type = T; }; template struct RemovePointerBase { using Type = T; }; template struct RemovePointerBase { using Type = T; }; template struct RemovePointerBase { using Type = T; }; } template using RemovePointer = typename detail::RemovePointerBase::Type; /* add pointer */ namespace detail { template struct AddPointerBase { using Type = RemoveReference *; }; } template using AddPointer = typename detail::AddPointerBase::Type; /* add lvalue reference */ namespace detail { template struct AddLr { using Type = T &; }; template struct AddLr { using Type = T &; }; template<> struct AddLr { using Type = void; }; template<> struct AddLr { using Type = void const; }; template<> struct AddLr { using Type = void volatile; }; template<> struct AddLr { using Type = void const volatile; }; } /* add rvalue reference */ namespace detail { template struct AddRr { using Type = T &&; }; template<> struct AddRr { using Type = void; }; template<> struct AddRr { using Type = void const; }; template<> struct AddRr { using Type = void volatile; }; template<> struct AddRr { using Type = void const volatile; }; } /* remove extent */ namespace detail { template struct RemoveExtentBase { using Type = T; }; template struct RemoveExtentBase { using Type = T; }; template struct RemoveExtentBase { using Type = T; }; } template using RemoveExtent = typename detail::RemoveExtentBase::Type; /* remove all extents */ namespace detail { template struct RemoveAllExtentsBase { using Type = T; }; template struct RemoveAllExtentsBase { using Type = RemoveAllExtentsBase; }; template struct RemoveAllExtentsBase { using Type = RemoveAllExtentsBase; }; } /* make (un)signed * * this is bad, but i don't see any better way * shamelessly copied from graphitemaster @ neothyne */ namespace detail { template struct TypeList { using First = T; using Rest = U; }; /* not a type */ struct TlNat { TlNat() = delete; TlNat(TlNat const &) = delete; TlNat &operator=(TlNat const &) = delete; ~TlNat() = delete; }; using Stypes = TypeList< sbyte, TypeList< short, TypeList< int, TypeList< long, TypeList > > > >; using Utypes = TypeList< byte, TypeList< ushort, TypeList< uint, TypeList< ulong, TypeList > > > >; template struct TypeFindFirst; template struct TypeFindFirst, N, true> { using Type = T; }; template struct TypeFindFirst, N, false> { using Type = typename TypeFindFirst::Type; }; template< typename T, typename U, bool = IsConst>, bool = IsVolatile> > struct ApplyCv { using Type = U; }; template struct ApplyCv { /* const */ using Type = U const; }; template struct ApplyCv { /* volatile */ using Type = U volatile; }; template struct ApplyCv { /* const volatile */ using Type = U const volatile; }; template struct ApplyCv { /* const */ using Type = U const &; }; template struct ApplyCv { /* volatile */ using Type = U volatile &; }; template struct ApplyCv { /* const volatile */ using Type = U const volatile &; }; template || IsEnum> struct MakeSignedCore {}; template || IsEnum> struct MakeUnsignedCore {}; template struct MakeSignedCore { using Type = typename TypeFindFirst::Type; }; template struct MakeUnsignedCore { using Type = typename TypeFindFirst::Type; }; template<> struct MakeSignedCore {}; template<> struct MakeSignedCore { using Type = short; }; template<> struct MakeSignedCore { using Type = int; }; template<> struct MakeSignedCore { using Type = long; }; template<> struct MakeSignedCore { using Type = sbyte; }; template<> struct MakeSignedCore { using Type = sbyte; }; template<> struct MakeSignedCore { using Type = short; }; template<> struct MakeSignedCore { using Type = int; }; template<> struct MakeSignedCore { using Type = long; }; template<> struct MakeSignedCore { using Type = llong; }; template<> struct MakeSignedCore { using Type = llong; }; template<> struct MakeUnsignedCore {}; template<> struct MakeUnsignedCore { using Type = ushort; }; template<> struct MakeUnsignedCore { using Type = uint; }; template<> struct MakeUnsignedCore { using Type = ulong; }; template<> struct MakeUnsignedCore { using Type = byte; }; template<> struct MakeUnsignedCore { using Type = byte; }; template<> struct MakeUnsignedCore { using Type = ushort; }; template<> struct MakeUnsignedCore { using Type = uint; }; template<> struct MakeUnsignedCore { using Type = ulong; }; template<> struct MakeUnsignedCore { using Type = ullong; }; template<> struct MakeUnsignedCore { using Type = ullong; }; template struct MakeSignedBase { using Type = typename ApplyCv>::Type >::Type; }; template struct MakeUnsignedBase { using Type = typename ApplyCv>::Type >::Type; }; } /* namespace detail */ template using MakeSigned = typename detail::MakeSignedBase::Type; template using MakeUnsigned = typename detail::MakeUnsignedBase::Type; /* conditional */ namespace detail { template struct ConditionalBase { using Type = T; }; template struct ConditionalBase { using Type = U; }; } template using Conditional = typename detail::ConditionalBase<_cond, T, U>::Type; /* enable if */ namespace detail { template struct EnableIfBase {}; template struct EnableIfBase { using Type = T; }; } template using EnableIf = typename detail::EnableIfBase::Type; /* result of call at compile time, from libc++ */ namespace detail { struct InvokeNat { InvokeNat() = delete; InvokeNat(InvokeNat const &) = delete; InvokeNat &operator=(InvokeNat const &) = delete; ~InvokeNat() = delete; }; struct InvokeAny { InvokeAny(...); }; template inline auto func_invoke(InvokeAny, A &&...) -> InvokeNat; /* forward declarations, later defined in functional */ template< typename F, typename T, typename ...A, typename = EnableIf< IsMemberFunctionPointer> && IsBaseOf< RemoveReference>>, RemoveReference > > > inline auto func_invoke(F &&f, T &&v, A &&...args) -> decltype((std::forward(v).*f)(std::forward(args)...)) { return (std::forward(v).*f)(std::forward(args)...); } template< typename F, typename T, typename ...A, typename = EnableIf< IsMemberFunctionPointer> && IsBaseOf< RemoveReference>>, RemoveReference > > > inline auto func_invoke(F &&f, T &&v, A &&...args) -> decltype(((*std::forward(v)).*f)(std::forward(args)...)) { return ((*std::forward(v)).*f)(std::forward(args)...); } template< typename F, typename T, typename = EnableIf< IsMemberObjectPointer> && IsBaseOf< RemoveReference>>, RemoveReference > > > inline auto func_invoke(F &&f, T &&v) -> decltype(std::forward(v).*f) { return std::forward(v).*f; } template< typename F, typename T, typename = EnableIf< IsMemberObjectPointer> && IsBaseOf< RemoveReference>>, RemoveReference > > > inline auto func_invoke(F &&f, T &&v) -> decltype((*std::forward(v)).*f) { return (*std::forward(v)).*f; } template inline auto func_invoke(F &&f, A &&...args) -> decltype(std::forward(f)(std::forward(args)...)) { return std::forward(f)(std::forward(args)...); } template struct FuncInvokableBase { using Type = decltype( func_invoke(std::declval(), std::declval()...) ); static constexpr bool value = !IsSame; }; template constexpr bool IsInvokable = FuncInvokableBase::value; template struct InvokeOfBase {}; template struct InvokeOfBase { using Type = typename FuncInvokableBase::Type; }; template using InvokeOf = typename InvokeOfBase, F, A...>::Type; template struct ResultOfBase {}; template struct ResultOfBase { using Type = InvokeOf; }; } /* namespace detail */ template using ResultOf = typename detail::ResultOfBase::Type; /* decay */ namespace detail { template struct DecayBase { private: using U = RemoveReference; public: using Type = Conditional< IsArray, RemoveExtent *, Conditional, AddPointer, RemoveCv> >; }; } template using Decay = typename detail::DecayBase::Type; /* common type */ namespace detail { template struct CommonTypeBase; template struct CommonTypeBase { using Type = Decay; }; template struct CommonTypeBase { using Type = Decay(): std::declval() )>; }; template struct CommonTypeBase { using Type = typename CommonTypeBase< typename CommonTypeBase::Type, V... >::Type; }; } template using CommonType = typename detail::CommonTypeBase::Type; /* aligned storage */ namespace detail { template struct AlignedTest { union Type { byte data[N]; std::max_align_t align; }; }; template struct AlignedStorageBase { struct Type { alignas(A) byte data[N]; }; }; } template::Type) > using AlignedStorage = typename detail::AlignedStorageBase::Type; /* aligned union */ namespace detail { template constexpr size_t AlignMax = 0; template constexpr size_t AlignMax = N; template constexpr size_t AlignMax = (N1 > N2) ? N1 : N2; template constexpr size_t AlignMax = AlignMax, N...>; template struct AlignedUnionBase { static constexpr size_t alignment_value = AlignMax; struct Type { alignas(alignment_value) byte data[AlignMax]; }; }; } /* namespace detail */ template using AlignedUnion = typename detail::AlignedUnionBase::Type; /* underlying type */ namespace detail { /* gotta wrap, in a struct otherwise clang ICEs... */ template struct UnderlyingTypeBase { using Type = __underlying_type(T); }; } template using UnderlyingType = typename detail::UnderlyingTypeBase::Type; } /* namespace ostd */ #endif