diff --git a/libcxx/include/type_traits b/libcxx/include/type_traits --- a/libcxx/include/type_traits +++ b/libcxx/include/type_traits @@ -544,9 +544,18 @@ // is_same +#if __has_keyword(__is_same) + +template +struct is_same : _BoolConstant<__is_same(_Tp, _Up)> { }; + +#else + template struct _LIBCPP_TEMPLATE_VIS is_same : public false_type {}; template struct _LIBCPP_TEMPLATE_VIS is_same<_Tp, _Tp> : public true_type {}; +#endif // __is_same + #if _LIBCPP_STD_VER > 14 && !defined(_LIBCPP_HAS_NO_VARIABLE_TEMPLATES) template _LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR bool is_same_v @@ -645,9 +654,18 @@ // is_const +#if __has_keyword(__is_const) + +template +struct is_const : _BoolConstant<__is_const(_Tp)> { }; + +#else + template struct _LIBCPP_TEMPLATE_VIS is_const : public false_type {}; template struct _LIBCPP_TEMPLATE_VIS is_const<_Tp const> : public true_type {}; +#endif // __has_keyword(__is_const) + #if _LIBCPP_STD_VER > 14 && !defined(_LIBCPP_HAS_NO_VARIABLE_TEMPLATES) template _LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR bool is_const_v @@ -656,9 +674,18 @@ // is_volatile +#if __has_keyword(__is_volatile) + +template +struct is_volatile : _BoolConstant<__is_volatile(_Tp)> { }; + +#else + template struct _LIBCPP_TEMPLATE_VIS is_volatile : public false_type {}; template struct _LIBCPP_TEMPLATE_VIS is_volatile<_Tp volatile> : public true_type {}; +#endif // __has_keyword(__is_volatile) + #if _LIBCPP_STD_VER > 14 && !defined(_LIBCPP_HAS_NO_VARIABLE_TEMPLATES) template _LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR bool is_volatile_v @@ -667,36 +694,79 @@ // remove_const +#if __has_keyword(__remove_const) + +template +struct _LIBCPP_TEMPLATE_VIS remove_const {typedef __remove_const(_Tp) type;}; + +#else + template struct _LIBCPP_TEMPLATE_VIS remove_const {typedef _Tp type;}; template struct _LIBCPP_TEMPLATE_VIS remove_const {typedef _Tp type;}; + +#endif // __has_keyword(__remove_const) + #if _LIBCPP_STD_VER > 11 template using remove_const_t = typename remove_const<_Tp>::type; #endif // remove_volatile +#if __has_keyword(__remove_volatile) + +template +struct _LIBCPP_TEMPLATE_VIS remove_volatile {typedef __remove_volatile(_Tp) type;}; + +#else + template struct _LIBCPP_TEMPLATE_VIS remove_volatile {typedef _Tp type;}; template struct _LIBCPP_TEMPLATE_VIS remove_volatile {typedef _Tp type;}; + +#endif // __has_keyword(__remove_volatile) + #if _LIBCPP_STD_VER > 11 template using remove_volatile_t = typename remove_volatile<_Tp>::type; #endif // remove_cv +#if __has_keyword(__remove_cv) + +template +struct _LIBCPP_TEMPLATE_VIS remove_cv {typedef __remove_cv(_Tp) type;}; + +#else + template struct _LIBCPP_TEMPLATE_VIS remove_cv {typedef typename remove_volatile::type>::type type;}; + +#endif // __has_keyword(__remove_cv) + #if _LIBCPP_STD_VER > 11 template using remove_cv_t = typename remove_cv<_Tp>::type; #endif // is_void +#if __has_keyword(__is_void) + +template +struct is_void : _BoolConstant<__is_void(_Tp)> { }; + +// This is never used but, we define it anyway for consistency. +template +struct __libcpp_is_void : _BoolConstant<__is_void(_Tp)> { }; + +#else + template struct __libcpp_is_void : public false_type {}; template <> struct __libcpp_is_void : public true_type {}; template struct _LIBCPP_TEMPLATE_VIS is_void : public __libcpp_is_void::type> {}; +#endif // __has_keyword(__is_void) + #if _LIBCPP_STD_VER > 14 && !defined(_LIBCPP_HAS_NO_VARIABLE_TEMPLATES) template _LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR bool is_void_v @@ -750,6 +820,18 @@ template <> struct __libcpp_is_integral<__uint128_t> : public true_type {}; #endif +#if __has_keyword(__is_integral) + +template +struct is_integral : _BoolConstant<__is_integral(_Tp)> { }; + +#if _LIBCPP_STD_VER > 14 +template +_LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR bool is_integral_v = __is_integral(_Tp); +#endif + +#else + template struct _LIBCPP_TEMPLATE_VIS is_integral : public __libcpp_is_integral::type> {}; @@ -759,6 +841,8 @@ = is_integral<_Tp>::value; #endif +#endif // __has_keyword(__is_integral) + // is_floating_point template struct __libcpp_is_floating_point : public false_type {}; @@ -766,6 +850,18 @@ template <> struct __libcpp_is_floating_point : public true_type {}; template <> struct __libcpp_is_floating_point : public true_type {}; +#if __has_keyword(__is_floating_point) + +template +struct is_floating_point : _BoolConstant<__is_floating_point(_Tp)> { }; + +#if _LIBCPP_STD_VER > 14 +template +_LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR bool is_floating_point_v = __is_floating_point(_Tp); +#endif + +#else + template struct _LIBCPP_TEMPLATE_VIS is_floating_point : public __libcpp_is_floating_point::type> {}; @@ -775,8 +871,17 @@ = is_floating_point<_Tp>::value; #endif +#endif // __has_keyword(__is_floating_point) + // is_array +#if __has_keyword(__is_array) + +template +struct is_array : _BoolConstant<__is_array(_Tp)> { }; + +#else + template struct _LIBCPP_TEMPLATE_VIS is_array : public false_type {}; template struct _LIBCPP_TEMPLATE_VIS is_array<_Tp[]> @@ -784,6 +889,8 @@ template struct _LIBCPP_TEMPLATE_VIS is_array<_Tp[_Np]> : public true_type {}; +#endif // __has_keyword(__is_array) + #if _LIBCPP_STD_VER > 14 && !defined(_LIBCPP_HAS_NO_VARIABLE_TEMPLATES) template _LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR bool is_array_v @@ -803,9 +910,18 @@ template struct __libcpp_remove_objc_qualifiers<_Tp __unsafe_unretained> { typedef _Tp type; }; #endif +#if __has_keyword(__is_pointer) + +template +struct is_pointer : _BoolConstant<__is_pointer(_Tp)> { }; + +#else // __has_keyword(__is_pointer) + template struct _LIBCPP_TEMPLATE_VIS is_pointer : public __libcpp_is_pointer::type>::type> {}; +#endif // __has_keyword(__is_pointer) + #if _LIBCPP_STD_VER > 14 && !defined(_LIBCPP_HAS_NO_VARIABLE_TEMPLATES) template _LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR bool is_pointer_v @@ -814,6 +930,21 @@ // is_reference +#if __has_keyword(__is_lvalue_reference) && \ + __has_keyword(is_rvalue_reference) && \ + __has_keyword(is_reference) + +template +struct is_lvalue_reference : _BoolConstant<__is_lvalue_reference(_Tp)> { }; + +template +struct is_rvalue_reference : _BoolConstant<__is_rvalue_reference(_Tp)> { }; + +template +struct is_reference : _BoolConstant<__is_reference(_Tp)> { }; + +#else // __has_keyword(__is_lvalue_reference) && etc... + template struct _LIBCPP_TEMPLATE_VIS is_lvalue_reference : public false_type {}; template struct _LIBCPP_TEMPLATE_VIS is_lvalue_reference<_Tp&> : public true_type {}; @@ -824,6 +955,8 @@ template struct _LIBCPP_TEMPLATE_VIS is_reference<_Tp&> : public true_type {}; template struct _LIBCPP_TEMPLATE_VIS is_reference<_Tp&&> : public true_type {}; +#endif // __has_keyword(__is_lvalue_reference) && etc... + #if _LIBCPP_STD_VER > 14 && !defined(_LIBCPP_HAS_NO_VARIABLE_TEMPLATES) template _LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR bool is_reference_v @@ -837,6 +970,7 @@ _LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR bool is_rvalue_reference_v = is_rvalue_reference<_Tp>::value; #endif + // is_union #if __has_feature(is_union) || defined(_LIBCPP_COMPILER_GCC) @@ -917,10 +1051,18 @@ }; }; +#if __has_keyword(__is_member_function_pointer) + +template +struct is_member_function_pointer : _BoolConstant<__is_member_function_pointer(_Tp)> { }; + +#else // __has_keyword(__is_member_function_pointer) template struct _LIBCPP_TEMPLATE_VIS is_member_function_pointer : public _BoolConstant< __libcpp_is_member_pointer::type>::__is_func > {}; +#endif // __has_keyword(__is_member_function_pointer) + #if _LIBCPP_STD_VER > 14 && !defined(_LIBCPP_HAS_NO_VARIABLE_TEMPLATES) template _LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR bool is_member_function_pointer_v @@ -929,9 +1071,18 @@ // is_member_pointer +#if __has_keyword(__is_member_pointer) + +template +struct is_member_pointer : _BoolConstant<__is_member_pointer(_Tp)> { }; + +#else // __has_keyword(__is_member_pointer) + template struct _LIBCPP_TEMPLATE_VIS is_member_pointer : public _BoolConstant< __libcpp_is_member_pointer::type>::__is_member > {}; + #endif // __has_keyword(__is_member_pointer) + #if _LIBCPP_STD_VER > 14 && !defined(_LIBCPP_HAS_NO_VARIABLE_TEMPLATES) template _LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR bool is_member_pointer_v @@ -940,9 +1091,18 @@ // is_member_object_pointer +#if __has_keyword(__is_member_object_pointer) + +template +struct is_member_object_pointer : _BoolConstant<__is_member_object_pointer(_Tp)> { }; + +#else // __has_keyword(__is_member_object_pointer) + template struct _LIBCPP_TEMPLATE_VIS is_member_object_pointer : public _BoolConstant< __libcpp_is_member_pointer::type>::__is_obj > {}; +#endif // __has_keyword(__is_member_object_pointer) + #if _LIBCPP_STD_VER > 14 && !defined(_LIBCPP_HAS_NO_VARIABLE_TEMPLATES) template _LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR bool is_member_object_pointer_v @@ -980,10 +1140,19 @@ // is_arithmetic +#if __has_keyword(__is_arithmetic) + +template +struct is_arithmetic : _BoolConstant<__is_arithmetic(_Tp)> { }; + +#else // __has_keyword(__is_arithmetic) + template struct _LIBCPP_TEMPLATE_VIS is_arithmetic : public integral_constant::value || is_floating_point<_Tp>::value> {}; +#endif // __has_keyword(__is_arithmetic) + #if _LIBCPP_STD_VER > 14 && !defined(_LIBCPP_HAS_NO_VARIABLE_TEMPLATES) template _LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR bool is_arithmetic_v @@ -992,11 +1161,21 @@ // is_fundamental +// Before clang 10, this builtin did not work for nullptr_t +#if __has_keyword(__is_fundamental) && _LIBCPP_CLANG_VER > 900 + +template +struct is_fundamental : _BoolConstant<__is_fundamental(_Tp)> { }; + +#else // __has_keyword(__is_fundamental) + template struct _LIBCPP_TEMPLATE_VIS is_fundamental : public integral_constant::value || __is_nullptr_t<_Tp>::value || is_arithmetic<_Tp>::value> {}; +#endif // __has_keyword(__is_fundamental) + #if _LIBCPP_STD_VER > 14 && !defined(_LIBCPP_HAS_NO_VARIABLE_TEMPLATES) template _LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR bool is_fundamental_v @@ -1005,6 +1184,14 @@ // is_scalar +// >= 11 because in C++03 nullptr isn't actually nullptr +#if __has_keyword(__is_scalar) && !defined(_LIBCPP_CXX03_LANG) + +template +struct is_scalar : _BoolConstant<__is_scalar(_Tp)> { }; + +#else // __has_keyword(__is_scalar) + template struct _LIBCPP_TEMPLATE_VIS is_scalar : public integral_constant::value || is_member_pointer<_Tp>::value || @@ -1014,6 +1201,8 @@ template <> struct _LIBCPP_TEMPLATE_VIS is_scalar : public true_type {}; +#endif // __has_keyword(__is_scalar) + #if _LIBCPP_STD_VER > 14 && !defined(_LIBCPP_HAS_NO_VARIABLE_TEMPLATES) template _LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR bool is_scalar_v @@ -1022,12 +1211,21 @@ // is_object +#if __has_keyword(__is_object) + +template +struct is_object : _BoolConstant<__is_object(_Tp)> { }; + +#else // __has_keyword(__is_object) + template struct _LIBCPP_TEMPLATE_VIS is_object : public integral_constant::value || is_array<_Tp>::value || is_union<_Tp>::value || is_class<_Tp>::value > {}; +#endif // __has_keyword(__is_object) + #if _LIBCPP_STD_VER > 14 && !defined(_LIBCPP_HAS_NO_VARIABLE_TEMPLATES) template _LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR bool is_object_v @@ -1036,9 +1234,19 @@ // is_compound +// >= 11 because in C++03 nullptr isn't actually nullptr +#if __has_keyword(__is_compound) && !defined(_LIBCPP_CXX03_LANG) + +template +struct is_compound : _BoolConstant<__is_compound(_Tp)> { }; + +#else // __has_keyword(__is_compound) + template struct _LIBCPP_TEMPLATE_VIS is_compound : public integral_constant::value> {}; +#endif // __has_keyword(__is_compound) + #if _LIBCPP_STD_VER > 14 && !defined(_LIBCPP_HAS_NO_VARIABLE_TEMPLATES) template _LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR bool is_compound_v @@ -1089,32 +1297,61 @@ // remove_reference +#if __has_keyword(__remove_reference) + +template +struct remove_reference { typedef __remove_reference(_Tp) type; }; + +#else // __has_keyword(__remove_reference) + template struct _LIBCPP_TEMPLATE_VIS remove_reference {typedef _LIBCPP_NODEBUG_TYPE _Tp type;}; template struct _LIBCPP_TEMPLATE_VIS remove_reference<_Tp&> {typedef _LIBCPP_NODEBUG_TYPE _Tp type;}; template struct _LIBCPP_TEMPLATE_VIS remove_reference<_Tp&&> {typedef _LIBCPP_NODEBUG_TYPE _Tp type;}; +#endif // __has_keyword(__remove_reference) + #if _LIBCPP_STD_VER > 11 template using remove_reference_t = typename remove_reference<_Tp>::type; #endif // add_lvalue_reference +#if __has_keyword(__add_lvalue_reference) + +template +struct add_lvalue_reference { typedef __add_lvalue_reference(_Tp) type; }; + +#else // __has_keyword(__add_lvalue_reference) + template ::value> struct __add_lvalue_reference_impl { typedef _LIBCPP_NODEBUG_TYPE _Tp type; }; template struct __add_lvalue_reference_impl<_Tp, true> { typedef _LIBCPP_NODEBUG_TYPE _Tp& type; }; template struct _LIBCPP_TEMPLATE_VIS add_lvalue_reference {typedef _LIBCPP_NODEBUG_TYPE typename __add_lvalue_reference_impl<_Tp>::type type;}; +#endif // __has_keyword(__add_lvalue_reference) + #if _LIBCPP_STD_VER > 11 template using add_lvalue_reference_t = typename add_lvalue_reference<_Tp>::type; #endif +// add_rvalue_reference + +#if __has_keyword(__add_rvalue_reference) + +template +struct add_rvalue_reference { typedef __add_rvalue_reference(_Tp) type; }; + +#else // __has_keyword(__add_rvalue_reference) + template ::value> struct __add_rvalue_reference_impl { typedef _LIBCPP_NODEBUG_TYPE _Tp type; }; template struct __add_rvalue_reference_impl<_Tp, true> { typedef _LIBCPP_NODEBUG_TYPE _Tp&& type; }; template struct _LIBCPP_TEMPLATE_VIS add_rvalue_reference {typedef _LIBCPP_NODEBUG_TYPE typename __add_rvalue_reference_impl<_Tp>::type type;}; +#endif // __has_keyword(__add_rvalue_reference) + #if _LIBCPP_STD_VER > 11 template using add_rvalue_reference_t = typename add_rvalue_reference<_Tp>::type; #endif @@ -1200,6 +1437,14 @@ // is_signed +// Before clang 10, this builtin did not work for floating points or enums +#if __has_keyword(__is_signed) && _LIBCPP_CLANG_VER > 900 + +template +struct is_signed : _BoolConstant<__is_signed(_Tp)> { }; + +#else // __has_keyword(__is_signed) + template ::value> struct __libcpp_is_signed_impl : public _LIBCPP_BOOL_CONSTANT(_Tp(-1) < _Tp(0)) {}; @@ -1213,6 +1458,8 @@ template struct _LIBCPP_TEMPLATE_VIS is_signed : public __libcpp_is_signed<_Tp> {}; +#endif // __has_keyword(__is_signed) + #if _LIBCPP_STD_VER > 14 && !defined(_LIBCPP_HAS_NO_VARIABLE_TEMPLATES) template _LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR bool is_signed_v @@ -1221,6 +1468,13 @@ // is_unsigned +#if __has_keyword(__is_unsigned) + +template +struct is_unsigned : _BoolConstant<__is_unsigned(_Tp)> { }; + +#else // __has_keyword(__is_unsigned) + template ::value> struct __libcpp_is_unsigned_impl : public _LIBCPP_BOOL_CONSTANT(_Tp(0) < _Tp(-1)) {}; @@ -1234,6 +1488,8 @@ template struct _LIBCPP_TEMPLATE_VIS is_unsigned : public __libcpp_is_unsigned<_Tp> {}; +#endif // __has_keyword(__is_unsigned) + #if _LIBCPP_STD_VER > 14 && !defined(_LIBCPP_HAS_NO_VARIABLE_TEMPLATES) template _LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR bool is_unsigned_v @@ -1257,6 +1513,13 @@ // extent +#if __has_keyword(__array_extent) + +template +struct extent : integral_constant { }; + +#else // __has_keyword(__array_extent) + template struct _LIBCPP_TEMPLATE_VIS extent : public integral_constant {}; template struct _LIBCPP_TEMPLATE_VIS extent<_Tp[], 0> @@ -1268,6 +1531,8 @@ template struct _LIBCPP_TEMPLATE_VIS extent<_Tp[_Np], _Ip> : public integral_constant::value> {}; +#endif // __has_keyword(__array_extent) + #if _LIBCPP_STD_VER > 14 && !defined(_LIBCPP_HAS_NO_VARIABLE_TEMPLATES) template _LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR size_t extent_v @@ -2120,6 +2385,13 @@ template struct __select_2nd { typedef _LIBCPP_NODEBUG_TYPE _Tp type; }; +#if __has_keyword(__is_assignable) + +template +struct is_assignable : _BoolConstant<__is_assignable(_Tp, _Up)> { }; + +#else // __has_keyword(__is_assignable) + template typename __select_2nd() = _VSTD::declval<_Arg>())), true_type>::type __is_assignable_test(int); @@ -2142,6 +2414,8 @@ struct is_assignable : public __is_assignable_imp<_Tp, _Arg> {}; +#endif // __has_keyword(__is_assignable) + #if _LIBCPP_STD_VER > 14 && !defined(_LIBCPP_HAS_NO_VARIABLE_TEMPLATES) template _LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR bool is_assignable_v @@ -2174,6 +2448,13 @@ // is_destructible +#if __has_keyword(__is_destructible) + +template +struct is_destructible : _BoolConstant<__is_destructible(_Tp)> { }; + +#else // __has_keyword(__is_destructible) + // if it's a reference, return true // if it's a function, return false // if it's void, return false @@ -2230,6 +2511,8 @@ struct is_destructible : public _VSTD::false_type {}; +#endif // __has_keyword(__is_destructible) + #if _LIBCPP_STD_VER > 14 && !defined(_LIBCPP_HAS_NO_VARIABLE_TEMPLATES) template _LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR bool is_destructible_v diff --git a/libcxx/test/std/utilities/meta/meta.rel/is_same.pass.cpp b/libcxx/test/std/utilities/meta/meta.rel/is_same.pass.cpp --- a/libcxx/test/std/utilities/meta/meta.rel/is_same.pass.cpp +++ b/libcxx/test/std/utilities/meta/meta.rel/is_same.pass.cpp @@ -50,6 +50,14 @@ static_assert((!std::is_same::value), ""); } +template +struct OverloadTest +{ + void fn(std::is_same) { } + void fn(std::false_type) { } + void x() { fn(std::false_type()); } +}; + class Class { public: @@ -70,5 +78,8 @@ test_is_not_same(); test_is_not_same(); + OverloadTest t; + (void)t; + return 0; }