PR66284 remove std::function special case for reference_wrapper
authorJonathan Wakely <jwakely@redhat.com>
Thu, 12 Jan 2017 14:28:38 +0000 (14:28 +0000)
committerJonathan Wakely <redi@gcc.gnu.org>
Thu, 12 Jan 2017 14:28:38 +0000 (14:28 +0000)
PR libstdc++/66284
* doc/xml/manual/intro.xml: Document LWG 2781 change.
* doc/html/*: Regenerate.
* include/std/functional (_Function_base::_Ref_manager): Remove.
(_Function_handler): Remove partial specializations for
reference_wrapper.
(function::target): Remove special case for const qualification.
* testsuite/20_util/function/6.cc: Adjust tests for target type.
* testsuite/20_util/function/7.cc: Likewise.
* testsuite/20_util/function/8.cc: Likewise.

From-SVN: r244364

libstdc++-v3/ChangeLog
libstdc++-v3/doc/html/manual/bugs.html
libstdc++-v3/doc/html/manual/documentation_hacking.html
libstdc++-v3/doc/xml/manual/intro.xml
libstdc++-v3/include/bits/std_function.h
libstdc++-v3/testsuite/20_util/function/6.cc
libstdc++-v3/testsuite/20_util/function/7.cc
libstdc++-v3/testsuite/20_util/function/8.cc

index 35fbb95f61780bb260554efd4c183320a4d5bcfd..7a70e250bf7fcbc12e12a948cd0a61e639684034 100644 (file)
@@ -1,3 +1,16 @@
+2017-01-12  Jonathan Wakely  <jwakely@redhat.com>
+
+       PR libstdc++/66284
+       * doc/xml/manual/intro.xml: Document LWG 2781 change.
+       * doc/html/*: Regenerate.
+       * include/std/functional (_Function_base::_Ref_manager): Remove.
+       (_Function_handler): Remove partial specializations for
+       reference_wrapper.
+       (function::target): Remove special case for const qualification.
+       * testsuite/20_util/function/6.cc: Adjust tests for target type.
+       * testsuite/20_util/function/7.cc: Likewise.
+       * testsuite/20_util/function/8.cc: Likewise.
+
 2017-01-11  Jonathan Wakely  <jwakely@redhat.com>
 
        PR libstdc++/78134
index ee39a954c5c8fb6779c597543cccd2361b64097e..439df7dc6fe7ec88cda8d6ef5bf92c71520a41eb 100644 (file)
        </em></span>
     </span></dt><dd><p>Safely detect <code class="code">tuple_size&lt;T&gt;::value</code> and
       only use it if valid.
+    </p></dd><dt><span class="term"><a class="link" href="../ext/lwg-defects.html#2781" target="_top">2781</a>:
+       <span class="emphasis"><em>Contradictory requirements for <code class="code">std::function</code>
+         and <code class="code">std::reference_wrapper</code>
+       </em></span>
+    </span></dt><dd><p>Remove special handling for <code class="code">reference_wrapper</code>
+      arguments and store them directly as the target object.
     </p></dd></dl></div></div></div><div class="navfooter"><hr /><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="license.html">Prev</a> </td><td width="20%" align="center"><a accesskey="u" href="status.html">Up</a></td><td width="40%" align="right"> <a accesskey="n" href="setup.html">Next</a></td></tr><tr><td width="40%" align="left" valign="top">License </td><td width="20%" align="center"><a accesskey="h" href="../index.html">Home</a></td><td width="40%" align="right" valign="top"> Chapter 2. Setup</td></tr></table></div></body></html>
\ No newline at end of file
index 26d8a6fba030fd4a8dbb3964689d13bf41e98c5d..7325cbee444419e679a8cf83e26d2672f0109efd 100644 (file)
        For Texinfo output, something that transforms valid Docbook
        XML to Texinfo is required. The default choice is <a class="link" href="http://docbook2x.sourceforge.net/" target="_top">docbook2X</a>.
       </p><p>
-       For epub output, the <a class="link" href="http://sourceforge.net/projects/docbook/files/epub3/" target="_top">stylesheets</a> for EPUB3 are required. These stylesheets are still in development. To validate the created file, <a class="link" href="https://code.google.com/p/epubcheck/" target="_top">epubcheck</a> is necessary.
+       For epub output, the <a class="link" href="https://sourceforge.net/projects/docbook/files/epub3/" target="_top">stylesheets</a> for EPUB3 are required. These stylesheets are still in development. To validate the created file, <a class="link" href="https://code.google.com/p/epubcheck/" target="_top">epubcheck</a> is necessary.
       </p></div><div class="section"><div class="titlepage"><div><div><h4 class="title"><a id="docbook.rules"></a>Generating the DocBook Files</h4></div></div></div><p>
        The following Makefile rules generate (in order): an HTML
        version of all the DocBook documentation, a PDF version of the
index d23008ad332dd29f136e41ac79983bfab532fe4c..db6e09a7793c0cde8c21567ddabc348f91c00863 100644 (file)
@@ -1116,6 +1116,15 @@ requirements of the license of GCC.
       only use it if valid.
     </para></listitem></varlistentry>
 
+    <varlistentry><term><link xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="../ext/lwg-defects.html#2781">2781</link>:
+       <emphasis>Contradictory requirements for <code>std::function</code>
+         and <code>std::reference_wrapper</code>
+       </emphasis>
+    </term>
+    <listitem><para>Remove special handling for <code>reference_wrapper</code>
+      arguments and store them directly as the target object.
+    </para></listitem></varlistentry>
+
   </variablelist>
 
  </section>
index f7bb22a313e5930ee90c22fa091d0aec63ca46f2..7d77e213b502aadab683f92948ee241ec0666b89 100644 (file)
@@ -268,41 +268,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
        { __functor._M_access<_Functor*>() = new _Functor(std::move(__f)); }
       };
 
-    template<typename _Functor>
-      class _Ref_manager : public _Base_manager<_Functor*>
-      {
-       typedef _Function_base::_Base_manager<_Functor*> _Base;
-
-      public:
-       static bool
-       _M_manager(_Any_data& __dest, const _Any_data& __source,
-                  _Manager_operation __op)
-       {
-         switch (__op)
-           {
-#if __cpp_rtti
-           case __get_type_info:
-             __dest._M_access<const type_info*>() = &typeid(_Functor);
-             break;
-#endif
-           case __get_functor_ptr:
-             __dest._M_access<_Functor*>() = *_Base::_M_get_pointer(__source);
-             return is_const<_Functor>::value;
-             break;
-
-           default:
-             _Base::_M_manager(__dest, __source, __op);
-           }
-         return false;
-       }
-
-       static void
-       _M_init_functor(_Any_data& __functor, reference_wrapper<_Functor> __f)
-       {
-         _Base::_M_init_functor(__functor, std::__addressof(__f.get()));
-       }
-      };
-
     _Function_base() : _M_manager(nullptr) { }
 
     ~_Function_base()
@@ -311,7 +276,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
        _M_manager(_M_functor, _M_functor, __destroy_functor);
     }
 
-
     bool _M_empty() const { return !_M_manager; }
 
     typedef bool (*_Manager_type)(_Any_data&, const _Any_data&,
@@ -354,36 +318,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       }
     };
 
-  template<typename _Res, typename _Functor, typename... _ArgTypes>
-    class _Function_handler<_Res(_ArgTypes...), reference_wrapper<_Functor> >
-    : public _Function_base::_Ref_manager<_Functor>
-    {
-      typedef _Function_base::_Ref_manager<_Functor> _Base;
-
-     public:
-      static _Res
-      _M_invoke(const _Any_data& __functor, _ArgTypes&&... __args)
-      {
-       return std::__invoke(**_Base::_M_get_pointer(__functor),
-                            std::forward<_ArgTypes>(__args)...);
-      }
-    };
-
-  template<typename _Functor, typename... _ArgTypes>
-    class _Function_handler<void(_ArgTypes...), reference_wrapper<_Functor> >
-    : public _Function_base::_Ref_manager<_Functor>
-    {
-      typedef _Function_base::_Ref_manager<_Functor> _Base;
-
-     public:
-      static void
-      _M_invoke(const _Any_data& __functor, _ArgTypes&&... __args)
-      {
-       std::__invoke(**_Base::_M_get_pointer(__functor),
-                     std::forward<_ArgTypes>(__args)...);
-      }
-    };
-
   template<typename _Class, typename _Member, typename _Res,
           typename... _ArgTypes>
     class _Function_handler<_Res(_ArgTypes...), _Member _Class::*>
@@ -677,15 +611,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
        *  @brief Access the stored target function object.
        *
        *  @return Returns a pointer to the stored target function object,
-       *  if @c typeid(Functor).equals(target_type()); otherwise, a NULL
+       *  if @c typeid(_Functor).equals(target_type()); otherwise, a NULL
        *  pointer.
        *
-       * This function will not throw an %exception.
+       * This function does not throw exceptions.
+       *
+       * @{
        */
       template<typename _Functor>       _Functor* target() noexcept;
 
-      /// @overload
       template<typename _Functor> const _Functor* target() const noexcept;
+      // @}
 #endif
 
     private:
@@ -755,17 +691,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       function<_Res(_ArgTypes...)>::
       target() noexcept
       {
-       if (typeid(_Functor) == target_type() && _M_manager)
-         {
-           _Any_data __ptr;
-           if (_M_manager(__ptr, _M_functor, __get_functor_ptr)
-               && !is_const<_Functor>::value)
-             return 0;
-           else
-             return __ptr._M_access<_Functor*>();
-         }
-       else
-         return 0;
+       const function* __const_this = this;
+       const _Functor* __func = __const_this->template target<_Functor>();
+       return const_cast<_Functor*>(__func);
       }
 
   template<typename _Res, typename... _ArgTypes>
@@ -781,7 +709,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
            return __ptr._M_access<const _Functor*>();
          }
        else
-         return 0;
+         return nullptr;
       }
 #endif
 
index 94c123434be2392be0577c990c8d5f839d0737a4..c224ec5412dd24581cdf4f0bb6a8a5edebf5d156 100644 (file)
 #include <functional>
 #include <testsuite_hooks.h>
 
-using namespace __gnu_test;
+template<typename T>
+  const T&
+  as_const(T& t)
+  { return t; }
+
+// Check that f's target is a reference_wrapper bound to obj.
+template<typename Function, typename T>
+  bool
+  wraps(Function& f, T& obj)
+  {
+    using ref_wrapper_type = std::reference_wrapper<T>;
+    auto* p = f.template target<ref_wrapper_type>();
+    return std::addressof(p->get()) == std::addressof(obj);
+  }
 
 struct secret {};
 
@@ -52,25 +65,24 @@ void test06()
   function<int()> f(ref(x));
   VERIFY( f );
   VERIFY( f() == 17 );
-  VERIFY( f.target_type() == typeid(noncopyable_function_object_type) );
-  VERIFY( f.target<noncopyable_function_object_type>() == &x );
+  VERIFY( f.target_type() == typeid(std::ref(x)) ); // LWG 2781
+  VERIFY( wraps(f, x) );
 
   function<int()> g = f;
   VERIFY( g );
   VERIFY( g() == 17 );
-  VERIFY( g.target_type() == typeid(noncopyable_function_object_type) );
-  VERIFY( g.target<noncopyable_function_object_type>() == &x );
+  VERIFY( g.target_type() == f.target_type() );
+  VERIFY( wraps(g, x) );
 
   function<int()> h = cref(x);
   VERIFY( h );
   VERIFY( h() == 42 );
-  VERIFY( h.target_type() == typeid(noncopyable_function_object_type) );
-  VERIFY( h.target<const noncopyable_function_object_type>() == &x );
-  VERIFY( h.target<const noncopyable_function_object_type>() == &x );
+  VERIFY( h.target_type() == typeid(std::cref(x)) );
+  VERIFY( wraps(h, as_const(x)) );
 
   const function<int()>& hc = h;
-  VERIFY( h.target<noncopyable_function_object_type>() == 0 );
-  VERIFY( hc.target<noncopyable_function_object_type>() == &x );
+  VERIFY( hc.target_type() == h.target_type() );
+  VERIFY( wraps(hc, as_const(x)) );
 }
 
 int main()
index 28337f4efd14e1fd5ba364f23e49a19f79dc6342..b10ecb8a161aaf6a406491d0d0e22a24a3a31607 100644 (file)
 #include <testsuite_hooks.h>
 #include <testsuite_tr1.h>
 
-using namespace __gnu_test;
+template<typename T>
+  const T&
+  as_const(T& t)
+  { return t; }
+
+// Check that f's target is a reference_wrapper bound to obj.
+template<typename Function, typename T>
+  bool
+  wraps(Function& f, T& obj)
+  {
+    using ref_wrapper_type = std::reference_wrapper<T>;
+    auto* p = f.template target<ref_wrapper_type>();
+    return std::addressof(p->get()) == std::addressof(obj);
+  }
 
 // Put reference_wrappers to function pointers into function<> wrappers
 void test07()
@@ -31,8 +44,9 @@ void test07()
   using std::function;
   using std::ref;
   using std::cref;
+  using std::reference_wrapper;
 
-  int (*fptr)(float) = truncate_float;
+  int (*fptr)(float) = __gnu_test::truncate_float;
 
   function<int(float)> f1(ref(fptr));
   VERIFY( f1 );
@@ -47,11 +61,11 @@ void test07()
 
   // target_type and target() functions
   const function<int(float)>& f1c = f1;
-  VERIFY( typeid(int(*)(float)) == f1.target_type() );
-  VERIFY( f1.target<int(*)(float)>() != 0 );
-  VERIFY( f1.target<int(*)(float)>() == &fptr );
-  VERIFY( f1c.target<int(*)(float)>() != 0 );
-  VERIFY( f1c.target<int(*)(float)>() == &fptr );
+  using ref_wrapper_type = reference_wrapper<int(*)(float)>;
+  VERIFY( typeid(ref_wrapper_type) == f1.target_type() );
+  VERIFY( f1.target<ref_wrapper_type>() != nullptr );
+  VERIFY( wraps(f1, fptr) );
+  VERIFY( wraps(f1c, fptr) );
 
   function<int(float)> f2(cref(fptr));
   VERIFY( f2 );
@@ -66,11 +80,11 @@ void test07()
 
   // target_type and target() functions
   const function<int(float)>& f2c = f2;
-  VERIFY( typeid(int(*)(float)) == f2.target_type() );
-  VERIFY( f2.target<int(*)(float)>() == 0 );
-  VERIFY( f2.target<int(* const)(float)>() == &fptr );
-  VERIFY( f2c.target<int(*)(float)>() != 0 );
-  VERIFY( f2c.target<int(*)(float)>() == &fptr );
+  using cref_wrapper_type = reference_wrapper<int(* const)(float)>;
+  VERIFY( typeid(cref_wrapper_type) == f2.target_type() );
+  VERIFY( wraps(f2, as_const(fptr)) );
+  VERIFY( f2c.target_type() == f2.target_type() );
+  VERIFY( wraps(f2c, as_const(fptr)) );
 }
 
 int main()
index 358399450a17db3cb0e153597a6a34252358cfb8..e641057d1511d1fa0386cd1c225a0c71c5dba992 100644 (file)
 #include <testsuite_hooks.h>
 #include <testsuite_tr1.h>
 
-using namespace __gnu_test;
+template<typename T>
+  const T&
+  as_const(T& t)
+  { return t; }
+
+// Check that f's target is a reference_wrapper bound to obj.
+template<typename Function, typename T>
+  bool
+  wraps(Function& f, T& obj)
+  {
+    using ref_wrapper_type = std::reference_wrapper<T>;
+    auto* p = f.template target<ref_wrapper_type>();
+    return std::addressof(p->get()) == std::addressof(obj);
+  }
 
 // Put reference_wrappers to member pointers
 void test08()
@@ -31,6 +44,8 @@ void test08()
   using std::function;
   using std::ref;
   using std::cref;
+  using std::reference_wrapper;
+  using __gnu_test::X;
 
   int X::* X_bar = &X::bar;
   int (X::* X_foo)() = &X::foo;
@@ -44,99 +59,92 @@ void test08()
   function<int(X&)> frm(ref(X_bar));
   VERIFY( frm );
   VERIFY( frm(x) == 17 );
-  VERIFY( typeid(int X::*) == frm.target_type() );
-  VERIFY( frm.target<int X::*>() == &X_bar );
+  VERIFY( typeid(ref(X_bar)) == frm.target_type() );
+  VERIFY( wraps(frm, X_bar) );
 
   function<int(X&)> fr(ref(X_foo));
   VERIFY( fr );
   VERIFY( fr(x) == 1 );
-  VERIFY( typeid(int (X::*)()) == fr.target_type() );
-  VERIFY( fr.target<int (X::*)()>() == &X_foo );
+  VERIFY( typeid(ref(X_foo)) == fr.target_type() );
+  VERIFY( wraps(fr, X_foo) );
 
   function<int(const X&)> frc(ref(X_foo_c));
   VERIFY( frc );
   VERIFY( frc(x) == 2 );
-  VERIFY( typeid(int (X::*)() const) == frc.target_type() );
-  VERIFY( frc.target<int (X::*)() const >() == &X_foo_c );
+  VERIFY( typeid(ref(X_foo_c)) == frc.target_type() );
+  VERIFY( wraps(frc, X_foo_c) );
 
   function<int(volatile X&)> frv(ref(X_foo_v));
   VERIFY( frv );
   VERIFY( frv(x) == 3 );
-  VERIFY( typeid(int (X::*)() volatile) == frv.target_type() );
-  VERIFY( *frv.target<int (X::*)() volatile >() == X_foo_v );
-  VERIFY( frv.target<int (X::*)() const volatile>() == 0 );
+  VERIFY( typeid(ref(X_foo_v)) == frv.target_type() );
+  VERIFY( wraps(frv, X_foo_v) );
 
   function<int(const volatile X&)> frcv(ref(X_foo_cv));
   VERIFY( frcv );
   VERIFY( frcv(x) == 4 );
-  VERIFY( typeid(int (X::*)() const volatile) == frcv.target_type() );
-  VERIFY( *frcv.target<int (X::*)() const volatile >() == X_foo_cv );
-  VERIFY( frcv.target<int (X::*)() const>() == 0 );
+  VERIFY( typeid(ref(X_foo_cv)) == frcv.target_type() );
+  VERIFY( wraps(frcv, X_foo_cv) );
 
   function<int(X*)> grm(ref(X_bar));
   VERIFY( grm );
   VERIFY( grm(&x) == 17 );
-  VERIFY( typeid(int X::*) == grm.target_type() );
-  VERIFY( *grm.target<int X::*>() == X_bar );
+  VERIFY( typeid(ref(X_bar)) == grm.target_type() );
+  VERIFY( wraps(grm, X_bar) );
 
   function<int(X*)> gr(ref(X_foo));
   VERIFY( gr );
   VERIFY( gr(&x) == 1 );
-  VERIFY( typeid(int (X::*)()) == gr.target_type() );
-  VERIFY( *gr.target<int (X::*)()>() == X_foo );
+  VERIFY( typeid(ref(X_foo)) == gr.target_type() );
+  VERIFY( wraps(gr, X_foo) );
 
   function<int(const X*)> grc(ref(X_foo_c));
   VERIFY( grc );
   VERIFY( grc(&x) == 2 );
-  VERIFY( typeid(int (X::*)() const) == grc.target_type() );
-  VERIFY( *grc.target<int (X::*)() const >() == X_foo_c );
+  VERIFY( typeid(ref(X_foo_c)) == grc.target_type() );
+  VERIFY( wraps(grc, X_foo_c) );
 
   function<int(volatile X*)> grv(ref(X_foo_v));
   VERIFY( grv );
   VERIFY( grv(&x) == 3 );
-  VERIFY( typeid(int (X::*)() volatile) == grv.target_type() );
-  VERIFY( *grv.target<int (X::*)() volatile >() == X_foo_v );
-  VERIFY( grv.target<int (X::*)() const volatile>() == 0 );
+  VERIFY( typeid(ref(X_foo_v)) == grv.target_type() );
+  VERIFY( wraps(grv, X_foo_v) );
 
   function<int(const volatile X*)> grcv(ref(X_foo_cv));
   VERIFY( grcv );
   VERIFY( grcv(&x) == 4 );
-  VERIFY( typeid(int (X::*)() const volatile) == grcv.target_type() );
-  VERIFY( *grcv.target<int (X::*)() const volatile >() == X_foo_cv );
-  VERIFY( grcv.target<int (X::*)() const>() == 0 );
+  VERIFY( typeid(ref(X_foo_cv)) == grcv.target_type() );
+  VERIFY( wraps(grcv, X_foo_cv) );
 
   function<int(X&)> hrm(cref(X_bar));
   VERIFY( hrm );
   VERIFY( hrm(x) == 17 );
-  VERIFY( typeid(int X::*) == hrm.target_type() );
-  VERIFY( hrm.target<int X::*>() == 0 );
-  VERIFY( hrm.target<int X::* const>() == &X_bar );
+  VERIFY( typeid(cref(X_bar)) == hrm.target_type() );
+  VERIFY( wraps(hrm, as_const(X_bar)) );
 
   function<int(X&)> hr(cref(X_foo));
   VERIFY( hr );
   VERIFY( hr(x) == 1 );
-  VERIFY( typeid(int (X::*)()) == hr.target_type() );
-  VERIFY( hr.target<int (X::* const)()>() == &X_foo );
+  VERIFY( typeid(cref(X_foo)) == hr.target_type() );
+  VERIFY( wraps(hr, as_const(X_foo)) );
 
   function<int(const X&)> hrc(cref(X_foo_c));
   VERIFY( hrc );
   VERIFY( hrc(x) == 2 );
-  VERIFY( typeid(int (X::*)() const) == hrc.target_type() );
-  VERIFY( hrc.target<int (X::* const)() const >() == &X_foo_c );
+  VERIFY( typeid(cref(X_foo_c)) == hrc.target_type() );
+  VERIFY( wraps(hrc, as_const(X_foo_c)) );
 
   function<int(volatile X&)> hrv(cref(X_foo_v));
   VERIFY( hrv );
   VERIFY( hrv(x) == 3 );
-  VERIFY( typeid(int (X::*)() volatile) == hrv.target_type() );
-  VERIFY( hrv.target<int (X::* const)() volatile >() == &X_foo_v );
-  VERIFY( hrv.target<int (X::* const)() const volatile>() == 0 );
+  VERIFY( typeid(cref(X_foo_v)) == hrv.target_type() );
+  VERIFY( wraps(hrv, as_const(X_foo_v)) );
 
   function<int(const volatile X&)> hrcv(cref(X_foo_cv));
   VERIFY( hrcv );
   VERIFY( hrcv(x) == 4 );
-  VERIFY( typeid(int (X::*)() const volatile) == hrcv.target_type() );
-  VERIFY( hrcv.target<int (X::* const)() const volatile >() == &X_foo_cv );
-  VERIFY( hrcv.target<int (X::* const)() const>() == 0 );
+  VERIFY( typeid(cref(X_foo_cv)) == hrcv.target_type() );
+  VERIFY( wraps(hrcv, as_const(X_foo_cv)) );
 }
 
 int main()