瀏覽代碼

Eliminate the C++0x-only is_convertible testing function that accepts
a cv-qualifier rvalue reference to the type, e.g.,

template <class _Tp> char __test(const volatile typename remove_reference<_Tp>::type&&);

The use of this function signature rather than the more
straightforward one used in C++98/03 mode, e.g.,

template <class _Tp> char __test(_Tp);

is broken in two ways:

1) An rvalue reference cannot bind to lvalues, so is_convertible<X&,
X&>::value would be false. This breaks two of the unique_ptr tests
on Clang and GCC >= 4.5. Prior GCC's seem to have allowed rvalue
references to bind to lvalues, allowing this bug to slip in.

2) By adding cv-qualifiers to the type we're converting to, we get
some incorrect "true" results for, e.g., is_convertible<const X&, X&>::value.





git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@124166 91177308-0d34-0410-b5e6-96231b3b80d8

Douglas Gregor 14 年之前
父節點
當前提交
f9e1c7e367
共有 2 個文件被更改,包括 15 次插入4 次删除
  1. 0 4
      include/type_traits
  2. 15 0
      test/utilities/meta/meta.rel/is_convertible.pass.cpp

+ 0 - 4
include/type_traits

@@ -600,11 +600,7 @@ template <class _Tp> struct _LIBCPP_VISIBLE is_abstract : public __libcpp_abstra
 
 
 namespace __is_convertible_imp
 namespace __is_convertible_imp
 {
 {
-#ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
-template <class _Tp> char  __test(const volatile typename remove_reference<_Tp>::type&&);
-#else
 template <class _Tp> char  __test(_Tp);
 template <class _Tp> char  __test(_Tp);
-#endif
 template <class _Tp> __two __test(...);
 template <class _Tp> __two __test(...);
 #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
 #ifndef _LIBCPP_HAS_NO_RVALUE_REFERENCES
 template <class _Tp> _Tp&& __source();
 template <class _Tp> _Tp&& __source();

+ 15 - 0
test/utilities/meta/meta.rel/is_convertible.pass.cpp

@@ -16,6 +16,10 @@
 typedef void Function();
 typedef void Function();
 typedef char Array[1];
 typedef char Array[1];
 
 
+class NonCopyable {
+  NonCopyable(NonCopyable&);
+};
+
 int main()
 int main()
 {
 {
     {
     {
@@ -366,4 +370,15 @@ int main()
     static_assert((!std::is_convertible<const char*, char*>::value), "");
     static_assert((!std::is_convertible<const char*, char*>::value), "");
     static_assert(( std::is_convertible<const char*, const char*>::value), "");
     static_assert(( std::is_convertible<const char*, const char*>::value), "");
     }
     }
+    {
+    static_assert((std::is_convertible<NonCopyable&, NonCopyable&>::value), "");
+    static_assert((std::is_convertible<NonCopyable&, const NonCopyable&>::value), "");
+    static_assert((std::is_convertible<NonCopyable&, const volatile NonCopyable&>::value), "");
+    static_assert((std::is_convertible<NonCopyable&, volatile NonCopyable&>::value), "");
+    static_assert((std::is_convertible<const NonCopyable&, const NonCopyable&>::value), "");
+    static_assert((std::is_convertible<const NonCopyable&, const volatile NonCopyable&>::value), "");
+    static_assert((std::is_convertible<volatile NonCopyable&, const volatile NonCopyable&>::value), "");
+    static_assert((std::is_convertible<const volatile NonCopyable&, const volatile NonCopyable&>::value), "");
+    static_assert((!std::is_convertible<const NonCopyable&, NonCopyable&>::value), "");
+    }
 }
 }