[PATCH] [libcxx] Correct SFINAE version of is_convertible to match spec and avoid triggering unnecessary compiler diagnostics

Eric Fiselier eric at efcs.ca
Thu Aug 21 03:59:17 PDT 2014


The actual change looks great, and I think its almost ready to land. I would like to see more complete test coverage in `meta.rel/is_convertible.pass.cpp` . I understand its demonstrated by the other tests passing but I would like a localized test case for the changes.

================
Comment at: include/type_traits:834-844
@@ -833,11 +833,13 @@
 namespace __is_convertible_imp
 {
-template <class _Tp> char  __test(_Tp);
-template <class _Tp> __two __test(...);
-#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
-template <class _Tp> _Tp&& __source();
-#else
-template <class _Tp> typename remove_reference<_Tp>::type& __source();
-#endif
+// Test derived from definition of is_convertible predicate in [meta.rel]p4.
+// declval() is used instead adding a new create() function because the
+// definitions are identical.
+template <class _Tp> char __helper(_Tp);
+
+template <class _Tp, class _Tf>
+typename enable_if<sizeof(__helper<_Tp>(declval<_Tf>())) == 1, char>::type
+    __test(int);
+template <class _Tp, class _Tf> __two __test(...);
 
 template <class _Tp, bool _IsArray =    is_array<_Tp>::value,
----------------
Can you add a test to `meta.rel/is_convertible.pass.cpp` to test this change?

================
Comment at: include/type_traits:887-894
@@ -884,10 +886,10 @@
 template <class _T1, class _T2> struct __is_convertible<_T1, _T2, 1, 0> : false_type {};
 
-template <class _T1> struct __is_convertible<_T1, const _T1&, 1, 0> : true_type {};
+template <class _T1> struct __is_convertible<_T1, typename add_const<_T1>::type&, 1, 0> : true_type {};
 #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
 template <class _T1> struct __is_convertible<_T1, _T1&&, 1, 0> : true_type {};
-template <class _T1> struct __is_convertible<_T1, const _T1&&, 1, 0> : true_type {};
-template <class _T1> struct __is_convertible<_T1, volatile _T1&&, 1, 0> : true_type {};
-template <class _T1> struct __is_convertible<_T1, const volatile _T1&&, 1, 0> : true_type {};
+template <class _T1> struct __is_convertible<_T1, typename add_const<_T1>::type&&, 1, 0> : true_type {};
+template <class _T1> struct __is_convertible<_T1, typename add_volatile<_T1>::type&&, 1, 0> : true_type {};
+template <class _T1> struct __is_convertible<_T1, typename add_cv<_T1>::type&&, 1, 0> : true_type {};
 #endif  // _LIBCPP_HAS_NO_RVALUE_REFERENCES
 
----------------
I can get `meta.rel/is_convertible.pass.cpp` passing w/ GCC-TOT if I only apply this part of the change.

http://reviews.llvm.org/D4341






More information about the cfe-commits mailing list