K-ballo created this revision.

Implement LWG2993, `reference_wrapper<T>` conversion from `T&&`.

The conversion fail test currently fails to fail (passes), due to 
https://bugs.llvm.org/show_bug.cgi?id=35332. Flagging it `XFAIL` does not seem 
to have any effect.


https://reviews.llvm.org/D40259

Files:
  include/__functional_base
  
test/std/utilities/function.objects/refwrap/refwrap.assign/copy_assign.pass.cpp
  
test/std/utilities/function.objects/refwrap/refwrap.const/type_conv_ctor.fail.cpp
  
test/std/utilities/function.objects/refwrap/refwrap.const/type_conv_ctor.pass.cpp

Index: test/std/utilities/function.objects/refwrap/refwrap.const/type_conv_ctor.pass.cpp
===================================================================
--- /dev/null
+++ test/std/utilities/function.objects/refwrap/refwrap.const/type_conv_ctor.pass.cpp
@@ -0,0 +1,58 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// <functional>
+
+// reference_wrapper
+
+// template <typename U> reference_wrapper(U&&);
+
+// XFAIL: c++98, c++03, c++11, c++14, c++17
+
+#include <functional>
+#include <cassert>
+
+struct convertible_to_int_ref {
+    int val = 0;
+    operator int&() { return val; }
+    operator int const&() const { return val; }
+};
+
+struct convertible_from_int {
+    convertible_from_int(int) {}
+};
+
+void meow(std::reference_wrapper<int>) {}
+void meow(convertible_from_int) {}
+
+int gi;
+std::reference_wrapper<int> purr() { return gi; };
+
+template <class T>
+void
+test(T& t)
+{
+    std::reference_wrapper<T> r(t);
+    assert(&r.get() == &t);
+}
+
+void f() {}
+
+int main()
+{
+    convertible_to_int_ref convi;
+    test(convi);
+    convertible_to_int_ref const convic;
+    test(convic);
+
+    {
+    meow(0);
+    (true) ? purr() : 0;
+    }
+}
Index: test/std/utilities/function.objects/refwrap/refwrap.const/type_conv_ctor.fail.cpp
===================================================================
--- /dev/null
+++ test/std/utilities/function.objects/refwrap/refwrap.const/type_conv_ctor.fail.cpp
@@ -0,0 +1,30 @@
+//===----------------------------------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is dual licensed under the MIT and the University of Illinois Open
+// Source Licenses. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+// <functional>
+
+// reference_wrapper
+
+// template <typename U> reference_wrapper(U&&);
+
+// XFAIL: c++98, c++03, c++11, c++14, c++17
+
+#include <functional>
+#include <cassert>
+
+struct convertible_to_float_ref {
+    float val = 0;
+    operator float const&() const { return val; }
+};
+
+int main()
+{
+    convertible_to_float_ref convf;
+    std::reference_wrapper<const int> r(convf);
+}
Index: test/std/utilities/function.objects/refwrap/refwrap.assign/copy_assign.pass.cpp
===================================================================
--- test/std/utilities/function.objects/refwrap/refwrap.assign/copy_assign.pass.cpp
+++ test/std/utilities/function.objects/refwrap/refwrap.assign/copy_assign.pass.cpp
@@ -20,6 +20,12 @@
 {
 };
 
+struct convertible_to_int_ref {
+    int val = 0;
+    operator int&() { return val; }
+    operator int const&() const { return val; }
+};
+
 template <class T>
 void
 test(T& t)
@@ -54,4 +60,11 @@
     test(i);
     const int j = 0;
     test(j);
+
+#if TEST_STD_VER > 17
+    convertible_to_int_ref convi;
+    test(convi);
+    convertible_to_int_ref const convic;
+    test(convic);
+#endif
 }
Index: include/__functional_base
===================================================================
--- include/__functional_base
+++ include/__functional_base
@@ -371,6 +371,15 @@
 #endif
 };
 
+#if _LIBCPP_STD_VER > 17
+template <class _Tp>
+inline _LIBCPP_INLINE_VISIBILITY
+_Tp& __lvref_bind(_Tp& r) _NOEXCEPT { return r; }
+
+template <class _Tp>
+_Tp& __lvref_bind(_Tp&& r) = delete;
+#endif
+
 template <class _Tp>
 class _LIBCPP_TEMPLATE_VIS reference_wrapper
     : public __weak_result_type<_Tp>
@@ -383,11 +392,22 @@
 
 public:
     // construct/copy/destroy
+#if _LIBCPP_STD_VER > 17
+    template <class _Up, class = enable_if_t<
+        !is_same<__uncvref_t<_Up>, reference_wrapper>::value
+    >, class = typename __void_t<
+        decltype(_VSTD::__lvref_bind<_Tp>(_VSTD::declval<_Up>()))
+    >::type>
+    _LIBCPP_INLINE_VISIBILITY reference_wrapper(_Up&& __u)
+    _NOEXCEPT_(noexcept(_VSTD::__lvref_bind<_Tp>(_VSTD::forward<_Up>(__u))))
+        : __f_(_VSTD::addressof(_VSTD::__lvref_bind<_Tp>(_VSTD::forward<_Up>(__u)))) {}
+#else
     _LIBCPP_INLINE_VISIBILITY reference_wrapper(type& __f) _NOEXCEPT
         : __f_(_VSTD::addressof(__f)) {}
 #ifndef _LIBCPP_CXX03_LANG
     private: reference_wrapper(type&&); public: // = delete; // do not bind to temps
 #endif
+#endif
 
     // access
     _LIBCPP_INLINE_VISIBILITY operator type&    () const _NOEXCEPT {return *__f_;}
@@ -509,6 +529,10 @@
 #endif // _LIBCPP_CXX03_LANG
 };
 
+#ifndef _LIBCPP_HAS_NO_DEDUCTION_GUIDES
+template <class _Tp>
+reference_wrapper(_Tp&) -> reference_wrapper<_Tp>;
+#endif
 
 template <class _Tp>
 inline _LIBCPP_INLINE_VISIBILITY
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to