From ff1760fac134c4d034d32979e944c3e5ab6e0cda Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Thu, 21 Oct 2021 15:21:15 -0700 Subject: [PATCH] util: add trait/macro for is_constexpr_constructible --- .../libvapours/include/vapours/defines.hpp | 23 ++ .../include/vapours/util/util_type_traits.hpp | 260 ++++++++++++++++++ 2 files changed, 283 insertions(+) diff --git a/libraries/libvapours/include/vapours/defines.hpp b/libraries/libvapours/include/vapours/defines.hpp index bf9fc2123..66359fbd2 100644 --- a/libraries/libvapours/include/vapours/defines.hpp +++ b/libraries/libvapours/include/vapours/defines.hpp @@ -80,3 +80,26 @@ namespace ams::impl { #define AMS_UNUSED(...) ::ams::impl::UnusedImpl(__VA_ARGS__) #define AMS_INFINITE_LOOP() do { __asm__ __volatile__("" ::: "memory"); } while (1) + +#define AMS__NARG__(...) AMS__NARG_I_(__VA_ARGS__,AMS__RSEQ_N()) +#define AMS__NARG_I_(...) AMS__ARG_N(__VA_ARGS__) +#define AMS__ARG_N( \ + _1, _2, _3, _4, _5, _6, _7, _8, _9,_10, \ + _11,_12,_13,_14,_15,_16,_17,_18,_19,_20, \ + _21,_22,_23,_24,_25,_26,_27,_28,_29,_30, \ + _31,_32,_33,_34,_35,_36,_37,_38,_39,_40, \ + _41,_42,_43,_44,_45,_46,_47,_48,_49,_50, \ + _51,_52,_53,_54,_55,_56,_57,_58,_59,_60, \ + _61,_62,_63,N,...) N +#define AMS__RSEQ_N() \ + 63,62,61,60, \ + 59,58,57,56,55,54,53,52,51,50, \ + 49,48,47,46,45,44,43,42,41,40, \ + 39,38,37,36,35,34,33,32,31,30, \ + 29,28,27,26,25,24,23,22,21,20, \ + 19,18,17,16,15,14,13,12,11,10, \ + 9,8,7,6,5,4,3,2,1,0 + +#define AMS__VMACRO_(name, n) name##_##n +#define AMS__VMACRO(name, n) AMS__VMACRO_(name, n) +#define AMS_VMACRO(func, ...) AMS__VMACRO(func, AMS__NARG__(__VA_ARGS__)) (__VA_ARGS__) diff --git a/libraries/libvapours/include/vapours/util/util_type_traits.hpp b/libraries/libvapours/include/vapours/util/util_type_traits.hpp index dea601140..448c18d69 100644 --- a/libraries/libvapours/include/vapours/util/util_type_traits.hpp +++ b/libraries/libvapours/include/vapours/util/util_type_traits.hpp @@ -26,4 +26,264 @@ namespace ams::util { struct ConstantInitializeTag final {}; constexpr inline const ConstantInitializeTag ConstantInitialize{}; + namespace impl { + + constexpr int ToIntegerForIsConstexprConstructible(...) { return {}; } + + template requires (std::is_constructible::value) + using ToIntegralConstantForIsConstexprConstructible = std::integral_constant; + + template::value> + std::true_type IsConstexprConstructibleImpl(int); + + template + std::false_type IsConstexprConstructibleImpl(long); + + template + consteval inline auto ConvertToLambdaForIsConstexprConstructible() { return [] { return T{}; }; } + + template + consteval inline auto ConvertToLambdaForIsConstexprConstructible() { return [] { return V; }; } + + namespace ambiguous_parse { + + struct AmbiguousParseHelperForIsConstexprConstructible { + + constexpr inline AmbiguousParseHelperForIsConstexprConstructible operator-() { return *this; } + + template + constexpr inline operator T() { + return T{}; + } + }; + + constexpr inline auto operator -(auto v, AmbiguousParseHelperForIsConstexprConstructible) { return v; } + + } + + #define AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(TYPE_OR_VALUE) [] { ::ams::util::impl::ambiguous_parse::AmbiguousParseHelperForIsConstexprConstructible p; auto v = (TYPE_OR_VALUE)-p; return v; } + + } + + template + using is_constexpr_constructible = decltype(impl::IsConstexprConstructibleImpl()...>(0)); + + template + using is_constexpr_constructible_by_values = decltype(impl::IsConstexprConstructibleImpl()...>(0)); + + #define AMS_UTIL_IS_CONSTEXPR_CONSTRUCTIBLE_1(_1) \ + (decltype(::ams::util::impl::IsConstexprConstructibleImpl<_1>(0))::value) + + #define AMS_UTIL_IS_CONSTEXPR_CONSTRUCTIBLE_2(_1, _2) \ + (decltype(::ams::util::impl::IsConstexprConstructibleImpl<_1, \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_2) \ + >(0))::value) + + #define AMS_UTIL_IS_CONSTEXPR_CONSTRUCTIBLE_3(_1, _2, _3) \ + (decltype(::ams::util::impl::IsConstexprConstructibleImpl<_1, \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_2), \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_3) \ + >(0))::value) + + #define AMS_UTIL_IS_CONSTEXPR_CONSTRUCTIBLE_4(_1, _2, _3, _4) \ + (decltype(::ams::util::impl::IsConstexprConstructibleImpl<_1, \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_2), \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_3), \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_4) \ + >(0))::value) + + #define AMS_UTIL_IS_CONSTEXPR_CONSTRUCTIBLE_5(_1, _2, _3, _4, _5) \ + (decltype(::ams::util::impl::IsConstexprConstructibleImpl<_1, \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_2), \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_3), \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_4), \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_5) \ + >(0))::value) + + #define AMS_UTIL_IS_CONSTEXPR_CONSTRUCTIBLE_6(_1, _2, _3, _4, _5, _6) \ + (decltype(::ams::util::impl::IsConstexprConstructibleImpl<_1, \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_2), \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_3), \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_4), \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_5), \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_6) \ + >(0))::value) + + #define AMS_UTIL_IS_CONSTEXPR_CONSTRUCTIBLE_7(_1, _2, _3, _4, _5, _6, _7) \ + (decltype(::ams::util::impl::IsConstexprConstructibleImpl<_1, \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_2), \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_3), \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_4), \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_5), \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_6), \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_7) \ + >(0))::value) + + #define AMS_UTIL_IS_CONSTEXPR_CONSTRUCTIBLE_8(_1, _2, _3, _4, _5, _6, _7, _8) \ + (decltype(::ams::util::impl::IsConstexprConstructibleImpl<_1, \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_2), \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_3), \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_4), \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_5), \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_6), \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_7), \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_8) \ + >(0))::value) + + #define AMS_UTIL_IS_CONSTEXPR_CONSTRUCTIBLE_9(_1, _2, _3, _4, _5, _6, _7, _8, _9) \ + (decltype(::ams::util::impl::IsConstexprConstructibleImpl<_1, \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_2), \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_3), \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_4), \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_5), \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_6), \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_7), \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_8), \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_9) \ + >(0))::value) + + #define AMS_UTIL_IS_CONSTEXPR_CONSTRUCTIBLE_10(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10) \ + (decltype(::ams::util::impl::IsConstexprConstructibleImpl<_1, \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_2), \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_3), \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_4), \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_5), \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_6), \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_7), \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_8), \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_9), \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_10) \ + >(0))::value) + + #define AMS_UTIL_IS_CONSTEXPR_CONSTRUCTIBLE_11(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11) \ + (decltype(::ams::util::impl::IsConstexprConstructibleImpl<_1, \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_2), \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_3), \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_4), \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_5), \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_6), \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_7), \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_8), \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_9), \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_10), \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_11) \ + >(0))::value) + + #define AMS_UTIL_IS_CONSTEXPR_CONSTRUCTIBLE_12(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12) \ + (decltype(::ams::util::impl::IsConstexprConstructibleImpl<_1, \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_2), \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_3), \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_4), \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_5), \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_6), \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_7), \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_8), \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_9), \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_10), \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_11), \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_12) \ + >(0))::value) + + #define AMS_UTIL_IS_CONSTEXPR_CONSTRUCTIBLE_13(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13) \ + (decltype(::ams::util::impl::IsConstexprConstructibleImpl<_1, \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_2), \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_3), \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_4), \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_5), \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_6), \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_7), \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_8), \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_9), \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_10), \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_11), \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_12), \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_13) \ + >(0))::value) + + #define AMS_UTIL_IS_CONSTEXPR_CONSTRUCTIBLE_14(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14) \ + (decltype(::ams::util::impl::IsConstexprConstructibleImpl<_1, \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_2), \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_3), \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_4), \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_5), \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_6), \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_7), \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_8), \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_9), \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_10), \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_11), \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_12), \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_13), \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_14) \ + >(0))::value) + + #define AMS_UTIL_IS_CONSTEXPR_CONSTRUCTIBLE_15(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15) \ + (decltype(::ams::util::impl::IsConstexprConstructibleImpl<_1, \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_2), \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_3), \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_4), \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_5), \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_6), \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_7), \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_8), \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_9), \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_10), \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_11), \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_12), \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_13), \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_14), \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_15) \ + >(0))::value) + + #define AMS_UTIL_IS_CONSTEXPR_CONSTRUCTIBLE_16(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16) \ + (decltype(::ams::util::impl::IsConstexprConstructibleImpl<_1, \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_2), \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_3), \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_4), \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_5), \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_6), \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_7), \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_8), \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_9), \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_10), \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_11), \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_12), \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_13), \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_14), \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_15), \ + AMS_UTIL_IMPL_CONVERT_TV_TO_LAMBDA(_16) \ + >(0))::value) + + #define AMS_UTIL_IS_CONSTEXPR_CONSTRUCTIBLE(...) AMS_VMACRO(AMS_UTIL_IS_CONSTEXPR_CONSTRUCTIBLE, __VA_ARGS__) + + #if 0 + namespace test { + + struct S { + private: + int m_v; + public: + S() { } + + constexpr S(int v) : m_v() { } + constexpr S(int v, double z) : m_v(v) { } + }; + + consteval inline int test_constexpr_int() { return 0; } + inline int test_not_constexpr_int() { return 0; } + + static_assert(!AMS_UTIL_IS_CONSTEXPR_CONSTRUCTIBLE(S)); + static_assert(AMS_UTIL_IS_CONSTEXPR_CONSTRUCTIBLE(S, int)); + static_assert(AMS_UTIL_IS_CONSTEXPR_CONSTRUCTIBLE(S, 0)); + static_assert(AMS_UTIL_IS_CONSTEXPR_CONSTRUCTIBLE(S, test_constexpr_int())); + static_assert(!AMS_UTIL_IS_CONSTEXPR_CONSTRUCTIBLE(S, test_not_constexpr_int())); + + static_assert(AMS_UTIL_IS_CONSTEXPR_CONSTRUCTIBLE(S, int, double)); + static_assert(AMS_UTIL_IS_CONSTEXPR_CONSTRUCTIBLE(S, int, 0.0)); + static_assert(AMS_UTIL_IS_CONSTEXPR_CONSTRUCTIBLE(S, 0, double)); + static_assert(AMS_UTIL_IS_CONSTEXPR_CONSTRUCTIBLE(S, 0, 0.0)); + + } + #endif + }