[libcxx-commits] [libcxx] 5ade17e - [libc++] Use builtin type traits whenever possible

via libcxx-commits libcxx-commits at lists.llvm.org
Thu Mar 19 09:57:37 PDT 2020


Author: zoecarver
Date: 2020-03-19T09:54:53-07:00
New Revision: 5ade17e0ca8b11f57cb15a1bee6d30a3815d8cac

URL: https://github.com/llvm/llvm-project/commit/5ade17e0ca8b11f57cb15a1bee6d30a3815d8cac
DIFF: https://github.com/llvm/llvm-project/commit/5ade17e0ca8b11f57cb15a1bee6d30a3815d8cac.diff

LOG: [libc++] Use builtin type traits whenever possible

This patch updates <type_traits> to use builtin type traits whenever
possible to improve compile times.

Differential Revision: https://reviews.llvm.org/D67900

Added: 
    

Modified: 
    libcxx/include/type_traits
    libcxx/test/std/utilities/meta/meta.rel/is_same.pass.cpp

Removed: 
    


################################################################################
diff  --git a/libcxx/include/type_traits b/libcxx/include/type_traits
index 6b8b855afc65..fc840ce7b3c0 100644
--- a/libcxx/include/type_traits
+++ b/libcxx/include/type_traits
@@ -544,6 +544,18 @@ template <bool _Bp, class _Tp = void> using enable_if_t = typename enable_if<_Bp
 
 // is_same
 
+#if __has_keyword(__is_same)
+
+template <class _Tp, class _Up>
+struct _LIBCPP_TEMPLATE_VIS is_same : _BoolConstant<__is_same(_Tp, _Up)> { };
+
+#if _LIBCPP_STD_VER > 14 && !defined(_LIBCPP_HAS_NO_VARIABLE_TEMPLATES)
+template <class _Tp, class _Up>
+_LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR bool is_same_v = __is_same(_Tp, _Up);
+#endif
+
+#else
+
 template <class _Tp, class _Up> struct _LIBCPP_TEMPLATE_VIS is_same           : public false_type {};
 template <class _Tp>            struct _LIBCPP_TEMPLATE_VIS is_same<_Tp, _Tp> : public true_type {};
 
@@ -553,6 +565,8 @@ _LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR bool is_same_v
     = is_same<_Tp, _Up>::value;
 #endif
 
+#endif // __is_same
+
 template <class _Tp, class _Up>
 using _IsSame = _BoolConstant<
 #ifdef __clang__
@@ -656,6 +670,18 @@ struct __two {char __lx[2];};
 
 // is_const
 
+#if __has_keyword(__is_const)
+
+template <class _Tp>
+struct _LIBCPP_TEMPLATE_VIS is_const : _BoolConstant<__is_const(_Tp)> { };
+
+#if _LIBCPP_STD_VER > 14 && !defined(_LIBCPP_HAS_NO_VARIABLE_TEMPLATES)
+template <class _Tp>
+_LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR bool is_const_v = __is_const(_Tp);
+#endif
+
+#else
+
 template <class _Tp> struct _LIBCPP_TEMPLATE_VIS is_const            : public false_type {};
 template <class _Tp> struct _LIBCPP_TEMPLATE_VIS is_const<_Tp const> : public true_type {};
 
@@ -665,8 +691,22 @@ _LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR bool is_const_v
     = is_const<_Tp>::value;
 #endif
 
+#endif // __has_keyword(__is_const)
+
 // is_volatile
 
+#if __has_keyword(__is_volatile)
+
+template <class _Tp>
+struct _LIBCPP_TEMPLATE_VIS is_volatile : _BoolConstant<__is_volatile(_Tp)> { };
+
+#if _LIBCPP_STD_VER > 14 && !defined(_LIBCPP_HAS_NO_VARIABLE_TEMPLATES)
+template <class _Tp>
+_LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR bool is_volatile_v = __is_volatile(_Tp);
+#endif
+
+#else
+
 template <class _Tp> struct _LIBCPP_TEMPLATE_VIS is_volatile               : public false_type {};
 template <class _Tp> struct _LIBCPP_TEMPLATE_VIS is_volatile<_Tp volatile> : public true_type {};
 
@@ -676,37 +716,87 @@ _LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR bool is_volatile_v
     = is_volatile<_Tp>::value;
 #endif
 
+#endif // __has_keyword(__is_volatile)
+
 // remove_const
 
+#if __has_keyword(__remove_const)
+
+template <class _Tp>
+struct _LIBCPP_TEMPLATE_VIS remove_const {typedef __remove_const(_Tp) type;};
+
+#if _LIBCPP_STD_VER > 11
+template <class _Tp> using remove_const_t = __remove_const(_Tp);
+#endif
+
+#else
+
 template <class _Tp> struct _LIBCPP_TEMPLATE_VIS remove_const            {typedef _Tp type;};
 template <class _Tp> struct _LIBCPP_TEMPLATE_VIS remove_const<const _Tp> {typedef _Tp type;};
 #if _LIBCPP_STD_VER > 11
 template <class _Tp> using remove_const_t = typename remove_const<_Tp>::type;
 #endif
 
+#endif // __has_keyword(__remove_const)
+
 // remove_volatile
 
+#if __has_keyword(__remove_volatile)
+
+template <class _Tp>
+struct _LIBCPP_TEMPLATE_VIS remove_volatile {typedef __remove_volatile(_Tp) type;};
+
+#if _LIBCPP_STD_VER > 11
+template <class _Tp> using remove_volatile_t = __remove_volatile(_Tp);
+#endif
+
+#else
+
 template <class _Tp> struct _LIBCPP_TEMPLATE_VIS remove_volatile               {typedef _Tp type;};
 template <class _Tp> struct _LIBCPP_TEMPLATE_VIS remove_volatile<volatile _Tp> {typedef _Tp type;};
 #if _LIBCPP_STD_VER > 11
 template <class _Tp> using remove_volatile_t = typename remove_volatile<_Tp>::type;
 #endif
 
+#endif // __has_keyword(__remove_volatile)
+
 // remove_cv
 
+#if __has_keyword(__remove_cv)
+
+template <class _Tp>
+struct _LIBCPP_TEMPLATE_VIS remove_cv {typedef __remove_cv(_Tp) type;};
+
+#if _LIBCPP_STD_VER > 11
+template <class _Tp> using remove_cv_t = __remove_cv(_Tp);
+#endif
+
+#else
+
 template <class _Tp> struct _LIBCPP_TEMPLATE_VIS remove_cv
 {typedef typename remove_volatile<typename remove_const<_Tp>::type>::type type;};
 #if _LIBCPP_STD_VER > 11
 template <class _Tp> using remove_cv_t = typename remove_cv<_Tp>::type;
 #endif
 
+#endif // __has_keyword(__remove_cv)
+
 // is_void
 
-template <class _Tp> struct __libcpp_is_void       : public false_type {};
-template <>          struct __libcpp_is_void<void> : public true_type {};
+#if __has_keyword(__is_void)
+
+template <class _Tp>
+struct _LIBCPP_TEMPLATE_VIS is_void : _BoolConstant<__is_void(_Tp)> { };
+
+#if _LIBCPP_STD_VER > 14 && !defined(_LIBCPP_HAS_NO_VARIABLE_TEMPLATES)
+template <class _Tp>
+_LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR bool is_void_v = __is_void(_Tp);
+#endif
+
+#else
 
 template <class _Tp> struct _LIBCPP_TEMPLATE_VIS is_void
-    : public __libcpp_is_void<typename remove_cv<_Tp>::type> {};
+    : public is_same<typename remove_cv<_Tp::type, void> {};
 
 #if _LIBCPP_STD_VER > 14 && !defined(_LIBCPP_HAS_NO_VARIABLE_TEMPLATES)
 template <class _Tp>
@@ -714,6 +804,8 @@ _LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR bool is_void_v
     = is_void<_Tp>::value;
 #endif
 
+#endif // __has_keyword(__is_void)
+
 // __is_nullptr_t
 
 template <class _Tp> struct __is_nullptr_t_impl       : public false_type {};
@@ -735,6 +827,18 @@ _LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR bool is_null_pointer_v
 
 // is_integral
 
+#if __has_keyword(__is_integral)
+
+template <class _Tp>
+struct _LIBCPP_TEMPLATE_VIS is_integral : _BoolConstant<__is_integral(_Tp)> { };
+
+#if _LIBCPP_STD_VER > 14
+template <class _Tp>
+_LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR bool is_integral_v = __is_integral(_Tp);
+#endif
+
+#else
+
 template <class _Tp> struct _LIBCPP_TEMPLATE_VIS is_integral
     : public _BoolConstant<__libcpp_is_integral<typename remove_cv<_Tp>::type>::value> {};
 
@@ -744,8 +848,22 @@ _LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR bool is_integral_v
     = is_integral<_Tp>::value;
 #endif
 
+#endif // __has_keyword(__is_integral)
+
 // is_floating_point
 
+#if __has_keyword(__is_floating_point)
+
+template <class _Tp>
+struct _LIBCPP_TEMPLATE_VIS is_floating_point : _BoolConstant<__is_floating_point(_Tp)> { };
+
+#if _LIBCPP_STD_VER > 14
+template <class _Tp>
+_LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR bool is_floating_point_v = __is_floating_point(_Tp);
+#endif
+
+#else
+
 template <class _Tp> struct __libcpp_is_floating_point              : public false_type {};
 template <>          struct __libcpp_is_floating_point<float>       : public true_type {};
 template <>          struct __libcpp_is_floating_point<double>      : public true_type {};
@@ -760,8 +878,22 @@ _LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR bool is_floating_point_v
     = is_floating_point<_Tp>::value;
 #endif
 
+#endif // __has_keyword(__is_floating_point)
+
 // is_array
 
+#if __has_keyword(__is_array)
+
+template <class _Tp>
+struct _LIBCPP_TEMPLATE_VIS is_array : _BoolConstant<__is_array(_Tp)> { };
+
+#if _LIBCPP_STD_VER > 14 && !defined(_LIBCPP_HAS_NO_VARIABLE_TEMPLATES)
+template <class _Tp>
+_LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR bool is_array_v = __is_array(_Tp);
+#endif
+
+#else
+
 template <class _Tp> struct _LIBCPP_TEMPLATE_VIS is_array
     : public false_type {};
 template <class _Tp> struct _LIBCPP_TEMPLATE_VIS is_array<_Tp[]>
@@ -775,6 +907,8 @@ _LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR bool is_array_v
     = is_array<_Tp>::value;
 #endif
 
+#endif // __has_keyword(__is_array)
+
 // is_pointer
 
 template <class _Tp> struct __libcpp_is_pointer       : public false_type {};
@@ -788,6 +922,18 @@ template <class _Tp> struct __libcpp_remove_objc_qualifiers<_Tp __autoreleasing>
 template <class _Tp> struct __libcpp_remove_objc_qualifiers<_Tp __unsafe_unretained> { typedef _Tp type; };
 #endif
 
+#if __has_keyword(__is_pointer)
+
+template<class _Tp>
+struct _LIBCPP_TEMPLATE_VIS is_pointer : _BoolConstant<__is_pointer(_Tp)> { };
+
+#if _LIBCPP_STD_VER > 14 && !defined(_LIBCPP_HAS_NO_VARIABLE_TEMPLATES)
+template <class _Tp>
+_LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR bool is_pointer_v = __is_pointer(_Tp);
+#endif
+
+#else // __has_keyword(__is_pointer)
+
 template <class _Tp> struct _LIBCPP_TEMPLATE_VIS is_pointer
     : public __libcpp_is_pointer<typename __libcpp_remove_objc_qualifiers<typename remove_cv<_Tp>::type>::type> {};
 
@@ -797,8 +943,36 @@ _LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR bool is_pointer_v
     = is_pointer<_Tp>::value;
 #endif
 
+#endif // __has_keyword(__is_pointer)
+
 // is_reference
 
+#if __has_keyword(__is_lvalue_reference) && \
+    __has_keyword(__is_rvalue_reference) && \
+    __has_keyword(__is_reference)
+
+template<class _Tp>
+struct _LIBCPP_TEMPLATE_VIS is_lvalue_reference : _BoolConstant<__is_lvalue_reference(_Tp)> { };
+
+template<class _Tp>
+struct _LIBCPP_TEMPLATE_VIS is_rvalue_reference : _BoolConstant<__is_rvalue_reference(_Tp)> { };
+
+template<class _Tp>
+struct _LIBCPP_TEMPLATE_VIS is_reference : _BoolConstant<__is_reference(_Tp)> { };
+
+#if _LIBCPP_STD_VER > 14 && !defined(_LIBCPP_HAS_NO_VARIABLE_TEMPLATES)
+template <class _Tp>
+_LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR bool is_reference_v = __is_reference(_Tp);
+
+template <class _Tp>
+_LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR bool is_lvalue_reference_v = __is_lvalue_reference(_Tp);
+
+template <class _Tp>
+_LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR bool is_rvalue_reference_v = __is_rvalue_reference(_Tp);
+#endif
+
+#else // __has_keyword(__is_lvalue_reference) && etc...
+
 template <class _Tp> struct _LIBCPP_TEMPLATE_VIS is_lvalue_reference       : public false_type {};
 template <class _Tp> struct _LIBCPP_TEMPLATE_VIS is_lvalue_reference<_Tp&> : public true_type {};
 
@@ -822,6 +996,9 @@ template <class _Tp>
 _LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR bool is_rvalue_reference_v
     = is_rvalue_reference<_Tp>::value;
 #endif
+
+#endif // __has_keyword(__is_lvalue_reference) && etc...
+
 // is_union
 
 #if __has_feature(is_union) || defined(_LIBCPP_COMPILER_GCC)
@@ -902,6 +1079,19 @@ template <class _Tp, class _Up> struct __libcpp_is_member_pointer<_Tp _Up::*> {
   };
 };
 
+#if __has_keyword(__is_member_function_pointer)
+
+template<class _Tp>
+struct _LIBCPP_TEMPLATE_VIS is_member_function_pointer
+    : _BoolConstant<__is_member_function_pointer(_Tp)> { };
+
+#if _LIBCPP_STD_VER > 14 && !defined(_LIBCPP_HAS_NO_VARIABLE_TEMPLATES)
+template <class _Tp>
+_LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR bool is_member_function_pointer_v
+    = __is_member_function_pointer(_Tp);
+#endif
+
+#else // __has_keyword(__is_member_function_pointer)
 
 template <class _Tp> struct _LIBCPP_TEMPLATE_VIS is_member_function_pointer
     : public _BoolConstant< __libcpp_is_member_pointer<typename remove_cv<_Tp>::type>::__is_func > {};
@@ -912,8 +1102,22 @@ _LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR bool is_member_function_pointer_v
     = is_member_function_pointer<_Tp>::value;
 #endif
 
+#endif // __has_keyword(__is_member_function_pointer)
+
 // is_member_pointer
 
+#if __has_keyword(__is_member_pointer)
+
+template<class _Tp>
+struct _LIBCPP_TEMPLATE_VIS is_member_pointer : _BoolConstant<__is_member_pointer(_Tp)> { };
+
+#if _LIBCPP_STD_VER > 14 && !defined(_LIBCPP_HAS_NO_VARIABLE_TEMPLATES)
+template <class _Tp>
+_LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR bool is_member_pointer_v = __is_member_pointer(_Tp);
+#endif
+
+#else // __has_keyword(__is_member_pointer)
+
 template <class _Tp> struct _LIBCPP_TEMPLATE_VIS is_member_pointer
  : public _BoolConstant< __libcpp_is_member_pointer<typename remove_cv<_Tp>::type>::__is_member > {};
 
@@ -923,8 +1127,24 @@ _LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR bool is_member_pointer_v
     = is_member_pointer<_Tp>::value;
 #endif
 
+#endif // __has_keyword(__is_member_pointer)
+
 // is_member_object_pointer
 
+#if __has_keyword(__is_member_object_pointer)
+
+template<class _Tp>
+struct _LIBCPP_TEMPLATE_VIS is_member_object_pointer
+    : _BoolConstant<__is_member_object_pointer(_Tp)> { };
+
+#if _LIBCPP_STD_VER > 14 && !defined(_LIBCPP_HAS_NO_VARIABLE_TEMPLATES)
+template <class _Tp>
+_LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR bool is_member_object_pointer_v
+    = __is_member_object_pointer(_Tp);
+#endif
+
+#else // __has_keyword(__is_member_object_pointer)
+
 template <class _Tp> struct _LIBCPP_TEMPLATE_VIS is_member_object_pointer
     : public _BoolConstant< __libcpp_is_member_pointer<typename remove_cv<_Tp>::type>::__is_obj >  {};
 
@@ -934,6 +1154,8 @@ _LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR bool is_member_object_pointer_v
     = is_member_object_pointer<_Tp>::value;
 #endif
 
+#endif // __has_keyword(__is_member_object_pointer)
+
 // is_enum
 
 #if __has_feature(is_enum) || defined(_LIBCPP_COMPILER_GCC)
@@ -941,6 +1163,11 @@ _LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR bool is_member_object_pointer_v
 template <class _Tp> struct _LIBCPP_TEMPLATE_VIS is_enum
     : public integral_constant<bool, __is_enum(_Tp)> {};
 
+#if _LIBCPP_STD_VER > 14 && !defined(_LIBCPP_HAS_NO_VARIABLE_TEMPLATES)
+template <class _Tp>
+_LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR bool is_enum_v = __is_enum(_Tp);
+#endif
+
 #else
 
 template <class _Tp> struct _LIBCPP_TEMPLATE_VIS is_enum
@@ -955,16 +1182,28 @@ template <class _Tp> struct _LIBCPP_TEMPLATE_VIS is_enum
                                      !is_class<_Tp>::value            &&
                                      !is_function<_Tp>::value         > {};
 
-#endif
-
 #if _LIBCPP_STD_VER > 14 && !defined(_LIBCPP_HAS_NO_VARIABLE_TEMPLATES)
 template <class _Tp>
 _LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR bool is_enum_v
     = is_enum<_Tp>::value;
 #endif
 
+#endif // __has_feature(is_enum) || defined(_LIBCPP_COMPILER_GCC)
+
 // is_arithmetic
 
+#if __has_keyword(__is_arithmetic)
+
+template<class _Tp>
+struct _LIBCPP_TEMPLATE_VIS is_arithmetic : _BoolConstant<__is_arithmetic(_Tp)> { };
+
+#if _LIBCPP_STD_VER > 14 && !defined(_LIBCPP_HAS_NO_VARIABLE_TEMPLATES)
+template <class _Tp>
+_LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR bool is_arithmetic_v = __is_arithmetic(_Tp);
+#endif
+
+#else // __has_keyword(__is_arithmetic)
+
 template <class _Tp> struct _LIBCPP_TEMPLATE_VIS is_arithmetic
     : public integral_constant<bool, is_integral<_Tp>::value      ||
                                      is_floating_point<_Tp>::value> {};
@@ -975,8 +1214,23 @@ _LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR bool is_arithmetic_v
     = is_arithmetic<_Tp>::value;
 #endif
 
+#endif // __has_keyword(__is_arithmetic)
+
 // is_fundamental
 
+// In clang 9 and lower, this builtin did not work for nullptr_t
+#if __has_keyword(__is_fundamental) && _LIBCPP_CLANG_VER > 900
+
+template<class _Tp>
+struct _LIBCPP_TEMPLATE_VIS is_fundamental : _BoolConstant<__is_fundamental(_Tp)> { };
+
+#if _LIBCPP_STD_VER > 14 && !defined(_LIBCPP_HAS_NO_VARIABLE_TEMPLATES)
+template <class _Tp>
+_LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR bool is_fundamental_v = __is_fundamental(_Tp);
+#endif
+
+#else // __has_keyword(__is_fundamental)
+
 template <class _Tp> struct _LIBCPP_TEMPLATE_VIS is_fundamental
     : public integral_constant<bool, is_void<_Tp>::value        ||
                                      __is_nullptr_t<_Tp>::value ||
@@ -988,8 +1242,23 @@ _LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR bool is_fundamental_v
     = is_fundamental<_Tp>::value;
 #endif
 
+#endif // __has_keyword(__is_fundamental)
+
 // is_scalar
 
+// >= 11 because in C++03 nullptr isn't actually nullptr
+#if __has_keyword(__is_scalar) && !defined(_LIBCPP_CXX03_LANG)
+
+template<class _Tp>
+struct _LIBCPP_TEMPLATE_VIS is_scalar : _BoolConstant<__is_scalar(_Tp)> { };
+
+#if _LIBCPP_STD_VER > 14 && !defined(_LIBCPP_HAS_NO_VARIABLE_TEMPLATES)
+template <class _Tp>
+_LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR bool is_scalar_v = __is_scalar(_Tp);
+#endif
+
+#else // __has_keyword(__is_scalar)
+
 template <class _Tp> struct __is_block : false_type {};
 #if defined(_LIBCPP_HAS_EXTENSION_BLOCKS)
 template <class _Rp, class ..._Args> struct __is_block<_Rp (^)(_Args...)> : true_type {};
@@ -1011,8 +1280,22 @@ _LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR bool is_scalar_v
     = is_scalar<_Tp>::value;
 #endif
 
+#endif // __has_keyword(__is_scalar)
+
 // is_object
 
+#if __has_keyword(__is_object)
+
+template<class _Tp>
+struct _LIBCPP_TEMPLATE_VIS is_object : _BoolConstant<__is_object(_Tp)> { };
+
+#if _LIBCPP_STD_VER > 14 && !defined(_LIBCPP_HAS_NO_VARIABLE_TEMPLATES)
+template <class _Tp>
+_LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR bool is_object_v = __is_object(_Tp);
+#endif
+
+#else // __has_keyword(__is_object)
+
 template <class _Tp> struct _LIBCPP_TEMPLATE_VIS is_object
     : public integral_constant<bool, is_scalar<_Tp>::value ||
                                      is_array<_Tp>::value  ||
@@ -1025,8 +1308,23 @@ _LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR bool is_object_v
     = is_object<_Tp>::value;
 #endif
 
+#endif // __has_keyword(__is_object)
+
 // is_compound
 
+// >= 11 because in C++03 nullptr isn't actually nullptr
+#if __has_keyword(__is_compound) && !defined(_LIBCPP_CXX03_LANG)
+
+template<class _Tp>
+struct _LIBCPP_TEMPLATE_VIS is_compound : _BoolConstant<__is_compound(_Tp)> { };
+
+#if _LIBCPP_STD_VER > 14 && !defined(_LIBCPP_HAS_NO_VARIABLE_TEMPLATES)
+template <class _Tp>
+_LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR bool is_compound_v = __is_compound(_Tp);
+#endif
+
+#else // __has_keyword(__is_compound)
+
 template <class _Tp> struct _LIBCPP_TEMPLATE_VIS is_compound
     : public integral_constant<bool, !is_fundamental<_Tp>::value> {};
 
@@ -1036,6 +1334,7 @@ _LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR bool is_compound_v
     = is_compound<_Tp>::value;
 #endif
 
+#endif // __has_keyword(__is_compound)
 
 // __is_referenceable  [defns.referenceable]
 
@@ -1080,6 +1379,13 @@ template <class _Tp> using add_cv_t = typename add_cv<_Tp>::type;
 
 // remove_reference
 
+#if __has_keyword(__remove_reference)
+
+template<class _Tp>
+struct _LIBCPP_TEMPLATE_VIS remove_reference { typedef __remove_reference(_Tp) type; };
+
+#else // __has_keyword(__remove_reference)
+
 template <class _Tp> struct _LIBCPP_TEMPLATE_VIS remove_reference        {typedef _LIBCPP_NODEBUG_TYPE _Tp type;};
 template <class _Tp> struct _LIBCPP_TEMPLATE_VIS remove_reference<_Tp&>  {typedef _LIBCPP_NODEBUG_TYPE _Tp type;};
 template <class _Tp> struct _LIBCPP_TEMPLATE_VIS remove_reference<_Tp&&> {typedef _LIBCPP_NODEBUG_TYPE _Tp type;};
@@ -1088,6 +1394,8 @@ template <class _Tp> struct _LIBCPP_TEMPLATE_VIS remove_reference<_Tp&&> {typede
 template <class _Tp> using remove_reference_t = typename remove_reference<_Tp>::type;
 #endif
 
+#endif // __has_keyword(__remove_reference)
+
 // add_lvalue_reference
 
 template <class _Tp, bool = __is_referenceable<_Tp>::value> struct __add_lvalue_reference_impl            { typedef _LIBCPP_NODEBUG_TYPE _Tp  type; };
@@ -1195,6 +1503,19 @@ template<class _Tp> using type_identity_t = typename type_identity<_Tp>::type;
 
 // is_signed
 
+// In clang 9 and earlier, this builtin did not work for floating points or enums
+#if __has_keyword(__is_signed) && _LIBCPP_CLANG_VER > 900
+
+template<class _Tp>
+struct _LIBCPP_TEMPLATE_VIS is_signed : _BoolConstant<__is_signed(_Tp)> { };
+
+#if _LIBCPP_STD_VER > 14 && !defined(_LIBCPP_HAS_NO_VARIABLE_TEMPLATES)
+template <class _Tp>
+_LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR bool is_signed_v = __is_signed(_Tp);
+#endif
+
+#else // __has_keyword(__is_signed)
+
 template <class _Tp, bool = is_integral<_Tp>::value>
 struct __libcpp_is_signed_impl : public _LIBCPP_BOOL_CONSTANT(_Tp(-1) < _Tp(0)) {};
 
@@ -1214,8 +1535,22 @@ _LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR bool is_signed_v
     = is_signed<_Tp>::value;
 #endif
 
+#endif // __has_keyword(__is_signed)
+
 // is_unsigned
 
+#if __has_keyword(__is_unsigned)
+
+template<class _Tp>
+struct _LIBCPP_TEMPLATE_VIS is_unsigned : _BoolConstant<__is_unsigned(_Tp)> { };
+
+#if _LIBCPP_STD_VER > 14 && !defined(_LIBCPP_HAS_NO_VARIABLE_TEMPLATES)
+template <class _Tp>
+_LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR bool is_unsigned_v = __is_unsigned(_Tp);
+#endif
+
+#else // __has_keyword(__is_unsigned)
+
 template <class _Tp, bool = is_integral<_Tp>::value>
 struct __libcpp_is_unsigned_impl : public _LIBCPP_BOOL_CONSTANT(_Tp(0) < _Tp(-1)) {};
 
@@ -1235,6 +1570,8 @@ _LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR bool is_unsigned_v
     = is_unsigned<_Tp>::value;
 #endif
 
+#endif // __has_keyword(__is_unsigned)
+
 // rank
 
 template <class _Tp> struct _LIBCPP_TEMPLATE_VIS rank
@@ -1252,6 +1589,19 @@ _LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR size_t rank_v
 
 // extent
 
+#if __has_keyword(__array_extent)
+
+template<class _Tp, size_t _Dim = 0>
+struct _LIBCPP_TEMPLATE_VIS extent
+    : integral_constant<size_t, __array_extent(_Tp, _Dim)> { };
+
+#if _LIBCPP_STD_VER > 14 && !defined(_LIBCPP_HAS_NO_VARIABLE_TEMPLATES)
+template <class _Tp, unsigned _Ip = 0>
+_LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR size_t extent_v = __array_extent(_Tp, _Ip);
+#endif
+
+#else // __has_keyword(__array_extent)
+
 template <class _Tp, unsigned _Ip = 0> struct _LIBCPP_TEMPLATE_VIS extent
     : public integral_constant<size_t, 0> {};
 template <class _Tp> struct _LIBCPP_TEMPLATE_VIS extent<_Tp[], 0>
@@ -1269,6 +1619,8 @@ _LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR size_t extent_v
     = extent<_Tp, _Ip>::value;
 #endif
 
+#endif // __has_keyword(__array_extent)
+
 // remove_extent
 
 template <class _Tp> struct _LIBCPP_TEMPLATE_VIS remove_extent
@@ -2114,6 +2466,18 @@ template <class ..._Tp> using common_type_t = typename common_type<_Tp...>::type
 
 template<typename, typename _Tp> struct __select_2nd { typedef _LIBCPP_NODEBUG_TYPE _Tp type; };
 
+#if __has_keyword(__is_assignable)
+
+template<class _Tp, class _Up>
+struct _LIBCPP_TEMPLATE_VIS is_assignable : _BoolConstant<__is_assignable(_Tp, _Up)> { };
+
+#if _LIBCPP_STD_VER > 14 && !defined(_LIBCPP_HAS_NO_VARIABLE_TEMPLATES)
+template <class _Tp, class _Arg>
+_LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR bool is_assignable_v = __is_assignable(_Tp, _Arg);
+#endif
+
+#else // __has_keyword(__is_assignable)
+
 template <class _Tp, class _Arg>
 typename __select_2nd<decltype((_VSTD::declval<_Tp>() = _VSTD::declval<_Arg>())), true_type>::type
 __is_assignable_test(int);
@@ -2142,6 +2506,8 @@ _LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR bool is_assignable_v
     = is_assignable<_Tp, _Arg>::value;
 #endif
 
+#endif  // __has_keyword(__is_assignable)
+
 // is_copy_assignable
 
 template <class _Tp> struct _LIBCPP_TEMPLATE_VIS is_copy_assignable
@@ -2168,6 +2534,18 @@ _LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR bool is_move_assignable_v
 
 // is_destructible
 
+#if __has_keyword(__is_destructible)
+
+template<class _Tp>
+struct _LIBCPP_TEMPLATE_VIS is_destructible : _BoolConstant<__is_destructible(_Tp)> { };
+
+#if _LIBCPP_STD_VER > 14 && !defined(_LIBCPP_HAS_NO_VARIABLE_TEMPLATES)
+template <class _Tp>
+_LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR bool is_destructible_v = __is_destructible(_Tp);
+#endif
+
+#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 +2608,8 @@ _LIBCPP_INLINE_VAR _LIBCPP_CONSTEXPR bool is_destructible_v
     = is_destructible<_Tp>::value;
 #endif
 
+#endif // __has_keyword(__is_destructible)
+
 // move
 
 template <class _Tp>
@@ -3859,7 +4239,6 @@ struct underlying_type : __underlying_type_impl<_Tp, is_enum<_Tp>::value> {};
 template <class _Tp> using underlying_type_t = typename underlying_type<_Tp>::type;
 #endif
 
-
 template <class _Tp, bool = is_enum<_Tp>::value>
 struct __sfinae_underlying_type
 {

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
index 739713bf4c2f..dd83f2240131 100644
--- 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 @@ void test_is_not_same()
     static_assert((!std::is_same<T, U>::value), "");
 }
 
+template <class T>
+struct OverloadTest
+{
+    void fn(std::is_same<T, int>) { }
+    void fn(std::false_type) { }
+    void x() { fn(std::false_type()); }
+};
+
 class Class
 {
 public:
@@ -70,5 +78,8 @@ int main(int, char**)
     test_is_not_same<int*, int&>();
     test_is_not_same<int&, int>();
 
+    OverloadTest<char> t;
+    (void)t;
+
   return 0;
 }


        


More information about the libcxx-commits mailing list