LWG 2993 reference_wrapper<T> conversion from T&&
authorJonathan Wakely <jwakely@redhat.com>
Fri, 15 Jun 2018 14:19:47 +0000 (15:19 +0100)
committerJonathan Wakely <redi@gcc.gnu.org>
Fri, 15 Jun 2018 14:19:47 +0000 (15:19 +0100)
* doc/xml/manual/intro.xml: Document LWG 2993 change.
* include/bits/refwrap.h (reference_wrapper(_Tp&)): Remove.
(reference_wrapper(_Tp&&)): Remove.
(reference_wrapper<_Up>(_Up&&)): Define new constructor as constrained
template.
(reference_wrapper): Add deduction guide.
* testsuite/20_util/reference_wrapper/deduction.cc: New.
* testsuite/20_util/reference_wrapper/lwg2993.cc: New.

From-SVN: r261632

libstdc++-v3/ChangeLog
libstdc++-v3/doc/xml/manual/intro.xml
libstdc++-v3/include/bits/refwrap.h
libstdc++-v3/testsuite/20_util/reference_wrapper/deduction.cc [new file with mode: 0644]
libstdc++-v3/testsuite/20_util/reference_wrapper/lwg2993.cc [new file with mode: 0644]

index aafffa58c5c4f58b186e559b2b523d5a84a82bca..31c8f36952029acb55625a521e84af8b3f780df5 100644 (file)
@@ -1,5 +1,15 @@
 2018-06-15  Jonathan Wakely  <jwakely@redhat.com>
 
+       LWG 2993 reference_wrapper<T> conversion from T&&
+       * doc/xml/manual/intro.xml: Document LWG 2993 change.
+       * include/bits/refwrap.h (reference_wrapper(_Tp&)): Remove.
+       (reference_wrapper(_Tp&&)): Remove.
+       (reference_wrapper<_Up>(_Up&&)): Define new constructor as constrained
+       template.
+       (reference_wrapper): Add deduction guide.
+       * testsuite/20_util/reference_wrapper/deduction.cc: New.
+       * testsuite/20_util/reference_wrapper/lwg2993.cc: New.
+
        LWG 3039 Unnecessary decay in thread and packaged_task
        * include/std/future (__constrain_pkgdtask): Replace with ...
        (packaged_task::__not_same): New alias template, using
index b0fc131d1eb9069ca9b88aecebb9a0a9fe29178f..90d43903def2858af53c802b18055b43d537a242 100644 (file)
@@ -1160,6 +1160,14 @@ requirements of the license of GCC.
     <listitem><para>Add noexcept.
     </para></listitem></varlistentry>
 
+    <varlistentry xml:id="manual.bugs.dr2993"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#2993">2993</link>:
+       <emphasis><code>reference_wrapper&lt;T&gt;</code> conversion from <code>T&amp;&amp;</code>
+       </emphasis>
+    </term>
+    <listitem><para>Replaced the constructors with a constrained template,
+      to prevent participation in overload resolution when not valid.
+    </para></listitem></varlistentry>
+
     <varlistentry xml:id="manual.bugs.dr3074"><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="&DR;#3074">3074</link>:
        <emphasis>Non-member functions for <code>valarray</code> should only deduce from the <code>valarray</code>
        </emphasis>
index c1d46705b6b0b89f69cb4c824c55754244fc5d12..2fdf231898fea872493bbeb87f694cb2053471c2 100644 (file)
@@ -291,14 +291,25 @@ _GLIBCXX_MEM_FN_TRAITS(&& noexcept, false_type, true_type)
     {
       _Tp* _M_data;
 
+      static _Tp* _S_fun(_Tp& __r) noexcept { return std::__addressof(__r); }
+      static void _S_fun(_Tp&&) = delete;
+
+      template<typename _Up, typename _Up2 = __remove_cvref_t<_Up>>
+       using __not_same
+         = typename enable_if<!is_same<reference_wrapper, _Up2>::value>::type;
+
     public:
       typedef _Tp type;
 
-      reference_wrapper(_Tp& __indata) noexcept
-      : _M_data(std::__addressof(__indata))
-      { }
-
-      reference_wrapper(_Tp&&) = delete;
+      // _GLIBCXX_RESOLVE_LIB_DEFECTS
+      // 2993. reference_wrapper<T> conversion from T&&
+      // 3041. Unnecessary decay in reference_wrapper
+      template<typename _Up, typename = __not_same<_Up>, typename
+               = decltype(reference_wrapper::_S_fun(std::declval<_Up>()))>
+       reference_wrapper(_Up&& __uref)
+       noexcept(noexcept(reference_wrapper::_S_fun(std::declval<_Up>())))
+       : _M_data(reference_wrapper::_S_fun(std::forward<_Up>(__uref)))
+       { }
 
       reference_wrapper(const reference_wrapper&) = default;
 
@@ -320,6 +331,10 @@ _GLIBCXX_MEM_FN_TRAITS(&& noexcept, false_type, true_type)
        }
     };
 
+#if __cpp_deduction_guides
+  template<typename _Tp>
+    reference_wrapper(_Tp&) -> reference_wrapper<_Tp>;
+#endif
 
   /// Denotes a reference should be taken to a variable.
   template<typename _Tp>
diff --git a/libstdc++-v3/testsuite/20_util/reference_wrapper/deduction.cc b/libstdc++-v3/testsuite/20_util/reference_wrapper/deduction.cc
new file mode 100644 (file)
index 0000000..cc5b260
--- /dev/null
@@ -0,0 +1,45 @@
+// Copyright (C) 2018 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-options "-std=gnu++17" }
+// { dg-do compile { target c++17 } }
+
+#include <functional>
+
+void
+test01()
+{
+  int i = 0;
+  std::reference_wrapper rw0(i);
+  [[maybe_unused]] std::reference_wrapper<int>* p0 = &rw0;
+  [[maybe_unused]] int& r0 = rw0;
+
+  std::reference_wrapper rw1(rw0);
+  [[maybe_unused]] std::reference_wrapper<int>* p1 = &rw1;
+  [[maybe_unused]] int& r1 = rw1;
+}
+
+void
+test02()
+{
+  const int i = 0;
+  std::reference_wrapper rw0(i);
+  [[maybe_unused]] std::reference_wrapper<const int>* p0 = &rw0;
+
+  std::reference_wrapper rw1(rw0);
+  [[maybe_unused]] std::reference_wrapper<const int>* p1 = &rw1;
+}
diff --git a/libstdc++-v3/testsuite/20_util/reference_wrapper/lwg2993.cc b/libstdc++-v3/testsuite/20_util/reference_wrapper/lwg2993.cc
new file mode 100644 (file)
index 0000000..0a33948
--- /dev/null
@@ -0,0 +1,55 @@
+// Copyright (C) 2018 Free Software Foundation, Inc.
+//
+// This file is part of the GNU ISO C++ Library.  This library is free
+// software; you can redistribute it and/or modify it under the
+// terms of the GNU General Public License as published by the
+// Free Software Foundation; either version 3, or (at your option)
+// any later version.
+
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License along
+// with this library; see the file COPYING3.  If not see
+// <http://www.gnu.org/licenses/>.
+
+// { dg-do compile { target c++11 } }
+
+#include <functional>
+
+// LWG 2993. reference_wrapper<T> conversion from T&&
+
+static_assert(std::is_convertible<std::reference_wrapper<int>,
+                                 std::reference_wrapper<const int>>::value,
+             "LWG 2993 enables qualification conversions");
+
+// The comments below are taken from the issue discussion and describe the
+// behaviour before the resolution of LWG 2993. There should be no errors now.
+
+struct convertible_from_int { convertible_from_int(int) { } };
+
+void
+test01()
+{
+
+  void meow(std::reference_wrapper<int>); //#1
+  void meow(convertible_from_int); //#2
+  // error, ambiguous; would unambiguously call #2 if #1 instead took int&
+  meow(0);
+}
+
+void
+test02()
+{
+  std::reference_wrapper<int> purr();
+
+  // error, ambiguous: ICS exists from int prvalue to
+  // reference_wrapper<int> and from reference_wrapper<int> to int
+  auto x = true ? purr() : 0;
+
+  // error: no member 'type' because the conditional
+  // expression is ill-formed
+  using t = std::common_type_t<std::reference_wrapper<int>, int>;
+}