re PR libstdc++/24803 ([c++0x] reference_wrapper and pointers to member functions)
authorJonathan Wakely <jwakely.gcc@gmail.com>
Wed, 5 Nov 2008 02:05:59 +0000 (02:05 +0000)
committerJonathan Wakely <redi@gcc.gnu.org>
Wed, 5 Nov 2008 02:05:59 +0000 (02:05 +0000)
PR libstdc++/24803
PR libstdc++/37351
* include/tr1_impl/functional (result_of,reference_wrapper): Update
to use C++0x features.
* testsuite/20_util/function_objects/return_types/result_of.cc: New.
* testsuite/20_util/function_objects/return_types/result_of_neg.cc:
New.
* testsuite/20_util/function_objects/return_types/result_of_ref.cc:
New.
* testsuite/20_util/reference_wrapper/24803.cc: Uncomment FIXMEs.

From-SVN: r141596

libstdc++-v3/ChangeLog
libstdc++-v3/include/tr1_impl/functional
libstdc++-v3/testsuite/20_util/function_objects/return_types/result_of.cc [new file with mode: 0644]
libstdc++-v3/testsuite/20_util/function_objects/return_types/result_of_neg.cc [new file with mode: 0644]
libstdc++-v3/testsuite/20_util/function_objects/return_types/result_of_ref.cc [new file with mode: 0644]
libstdc++-v3/testsuite/20_util/reference_wrapper/24803.cc

index 47ffacc35cea3c6343bf11a200f5922ca95b9ece..47eaf4936fd5cee469b536d2e378f12a0ea95cb0 100644 (file)
@@ -1,3 +1,16 @@
+2008-11-05  Jonathan Wakely  <jwakely.gcc@gmail.com>
+
+       PR libstdc++/24803
+       PR libstdc++/37351
+       * include/tr1_impl/functional (result_of,reference_wrapper): Update
+       to use C++0x features.
+       * testsuite/20_util/function_objects/return_types/result_of.cc: New.
+       * testsuite/20_util/function_objects/return_types/result_of_neg.cc:
+       New.
+       * testsuite/20_util/function_objects/return_types/result_of_ref.cc:
+       New.
+       * testsuite/20_util/reference_wrapper/24803.cc: Uncomment FIXMEs.
+
 2008-11-03  Paolo Carlini  <paolo.carlini@oracle.com>
 
        * include/bits/locale_facets.tcc (num_get<>::do_get(iter_type,
index b819374f92d42df50c422f45c7de1802b0a210b8..6432181bfc02557683741d970603352aa5062392 100644 (file)
@@ -153,6 +153,7 @@ _GLIBCXX_BEGIN_NAMESPACE_TR1
   template<typename _Signature>
     class result_of;
 
+#ifdef _GLIBCXX_INCLUDE_AS_TR1
   /**
    *  Actual implementation of result_of. When _Has_result_type is
    *  true, gets its result from _Weak_result_type. Otherwise, uses
@@ -210,6 +211,104 @@ _GLIBCXX_BEGIN_NAMESPACE_TR1
       typedef void type;
     };
 
+#else
+  /**
+   *  Actual implementation of std::result_of.
+  */
+  template<bool _Is_mem_obj_ptr, bool _Is_mem_fun_ptr, typename _Signature>
+    struct _Result_of_impl;
+
+  // Helper functions used by _Result_of_impl.
+  template<typename _ArgT>
+    struct _Result_of_arg
+    {
+      // http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#904
+#if 0
+      static typename conditional<is_reference<_ArgT>::value,
+                      typename add_lvalue_reference<_ArgT>::type,
+                      typename add_rvalue_reference<_ArgT>::type>::type
+      _S_fwd();
+#else
+      static typename add_rvalue_reference<_ArgT>::type
+      _S_fwd();
+#endif
+    };
+
+  template<typename _Tp, bool _NoDeref>
+    struct _Result_of_lhs
+    {
+      static _Tp _S_fwd();
+    };
+  template<typename _Tp>
+    struct _Result_of_lhs<_Tp, false>
+    {
+      static decltype( *_Result_of_lhs<_Tp,true>::_S_fwd() ) _S_fwd();
+    };
+
+  // Handle member data pointers.
+  template<typename _Res, typename _Class, typename _T1>
+    class _Result_of_impl<true, false, _Res _Class::* (_T1)>
+    {
+      typedef typename remove_reference<_T1>::type _T2;
+      typedef _Result_of_lhs<_T1, is_base_of<_Class, _T2>::value> _Fwd_lhs;
+      typedef _Res _Class::*_MemPtr;
+
+    public:
+      typedef decltype( (_Fwd_lhs::_S_fwd().*(_MemPtr())) ) type;
+    };
+
+  // Handle member function pointers.
+  template<typename _MemFun, typename _T1, typename... _ArgTypes>
+    class _Result_of_impl<false, true, _MemFun (_T1, _ArgTypes...)>
+    {
+      template<typename>
+        struct _Get_class;
+
+      template<typename _Res, typename _Class, typename... _Args>
+        struct _Get_class<_Res (_Class::*)(_Args...)>
+        { typedef _Class type; };
+      template<typename _Res, typename _Class, typename... _Args>
+        struct _Get_class<_Res (_Class::*)(_Args...) const>
+        { typedef _Class type; };
+      template<typename _Res, typename _Class, typename... _Args>
+        struct _Get_class<_Res (_Class::*)(_Args...) volatile>
+        { typedef _Class type; };
+      template<typename _Res, typename _Class, typename... _Args>
+        struct _Get_class<_Res (_Class::*)(_Args...) const volatile>
+        { typedef _Class type; };
+
+      typedef typename _Get_class<_MemFun>::type _Class;
+      typedef typename remove_reference<_T1>::type _T2;
+      typedef _Result_of_lhs<_T1, is_base_of<_Class, _T2>::value> _Fwd_lhs;
+
+    public:
+      typedef decltype( (_Fwd_lhs::_S_fwd().*(_MemFun())) (
+            _Result_of_arg<_ArgTypes>::_S_fwd() ... ) ) type;
+    };
+
+  // Handle other callable types.
+  template<typename _Functor, typename... _ArgTypes>
+    class _Result_of_impl<false, false, _Functor(_ArgTypes...)>
+    {
+      // get an example of the callable type
+      static typename add_rvalue_reference<_Functor>::type
+      _S_fwd_functor();
+
+    public:
+      typedef decltype( _Result_of_impl::_S_fwd_functor() (
+            _Result_of_arg<_ArgTypes>::_S_fwd() ... ) ) type;
+    };
+
+  template<typename _Functor, typename... _ArgTypes>
+    class result_of<_Functor(_ArgTypes...)>
+    : public _Result_of_impl<
+      is_member_object_pointer<_Functor>::value,
+      is_member_function_pointer<_Functor>::value,
+      _Functor(_ArgTypes...)>
+    {
+    };
+#endif
+
   /// Determines if the type _Tp derives from unary_function.
   template<typename _Tp>
     struct _Derives_from_unary_function : __sfinae_types
@@ -255,6 +354,7 @@ _GLIBCXX_BEGIN_NAMESPACE_TR1
       typedef _Tp* type;
     };
 
+#ifdef _GLIBCXX_INCLUDE_AS_TR1
   /**
    * Invoke a function object, which may be either a member pointer or a
    * function object. The first parameter will tell which.
@@ -297,6 +397,50 @@ _GLIBCXX_BEGIN_NAMESPACE_TR1
     {
       return __f(__args...);
     }
+#else
+  /**
+   * Invoke a function object, which may be either a member pointer or a
+   * function object. The first parameter will tell which.
+   */
+  template<typename _Functor, typename... _Args>
+    inline
+    typename enable_if<
+             (!is_member_pointer<_Functor>::value
+              && !is_function<_Functor>::value
+              && !is_function<typename remove_pointer<_Functor>::type>::value),
+             typename result_of<_Functor(_Args...)>::type
+           >::type
+    __invoke(_Functor& __f, _Args&&... __args)
+    {
+      return __f(std::forward<_Args>(__args)...);
+    }
+
+  template<typename _Functor, typename... _Args>
+    inline
+    typename enable_if<
+             (is_member_pointer<_Functor>::value
+              && !is_function<_Functor>::value
+              && !is_function<typename remove_pointer<_Functor>::type>::value),
+             typename result_of<_Functor(_Args...)>::type
+           >::type
+    __invoke(_Functor& __f, _Args&&... __args)
+    {
+      return mem_fn(__f)(std::forward<_Args>(__args)...);
+    }
+
+  // To pick up function references (that will become function pointers)
+  template<typename _Functor, typename... _Args>
+    inline
+    typename enable_if<
+             (is_pointer<_Functor>::value
+              && is_function<typename remove_pointer<_Functor>::type>::value),
+             typename result_of<_Functor(_Args...)>::type
+           >::type
+    __invoke(_Functor __f, _Args&&... __args)
+    {
+      return __f(std::forward<_Args>(__args)...);
+    }
+#endif
 
   /**
    *  Knowing which of unary_function and binary_function _Tp derives
@@ -440,9 +584,17 @@ _GLIBCXX_BEGIN_NAMESPACE_TR1
     public:
       typedef _Tp type;
 
+#ifdef _GLIBCXX_INCLUDE_AS_TR1
       explicit
       reference_wrapper(_Tp& __indata): _M_data(&__indata)
       { }
+#else
+      reference_wrapper(_Tp& __indata): _M_data(&__indata)
+      { }
+
+      explicit
+      reference_wrapper(_Tp&&) = delete;
+#endif
 
       reference_wrapper(const reference_wrapper<_Tp>& __inref):
       _M_data(__inref._M_data)
@@ -462,12 +614,21 @@ _GLIBCXX_BEGIN_NAMESPACE_TR1
       get() const
       { return *_M_data; }
 
+#ifdef _GLIBCXX_INCLUDE_AS_TR1
       template<typename... _Args>
         typename result_of<_M_func_type(_Args...)>::type
         operator()(_Args&... __args) const
         {
          return __invoke(get(), __args...);
        }
+#else
+      template<typename... _Args>
+        typename result_of<_M_func_type(_Args...)>::type
+        operator()(_Args&&... __args) const
+        {
+         return __invoke(get(), std::forward<_Args>(__args)...);
+       }
+#endif
     };
 
 
diff --git a/libstdc++-v3/testsuite/20_util/function_objects/return_types/result_of.cc b/libstdc++-v3/testsuite/20_util/function_objects/return_types/result_of.cc
new file mode 100644 (file)
index 0000000..50f64b6
--- /dev/null
@@ -0,0 +1,76 @@
+// { dg-options "-std=gnu++0x" }
+// Copyright (C) 2008 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 2, 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 COPYING.  If not, write to the Free
+// Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+// USA.
+
+// 20.6.4 function object return types [func.ret]
+#include <functional>
+#include <testsuite_hooks.h>
+
+struct nested_result_type
+{
+    typedef float result_type;
+    int operator()();
+};
+
+struct nested_result_template
+{
+  template<typename F> struct result { typedef float type; };
+  int operator()(int);
+};
+
+struct cv_overload
+{
+  int operator()(int);
+  char operator()(char) const;
+  float operator()(float) volatile;
+};
+
+struct default_args
+{
+    int operator()(int* = 0, int* = 0);
+    void operator()(void*);
+};
+
+class X {};
+
+void test01()
+{
+  bool test __attribute__((unused)) = true;
+
+  using std::result_of;
+  using std::is_same;
+
+  typedef int (*func_ptr)(float, double);
+  typedef int (&func_ref)(float, double);
+
+  VERIFY((is_same<result_of<nested_result_type()>::type, int>::value));
+  VERIFY((is_same<result_of<nested_result_template(int)>::type, int>::value));
+  VERIFY((is_same<result_of<cv_overload(int)>::type, int>::value));
+  VERIFY((is_same<result_of<const cv_overload(int)>::type, char>::value));
+  VERIFY((is_same<result_of<volatile cv_overload(int)>::type, float>::value));
+  VERIFY((is_same<result_of<default_args(int*)>::type, int>::value));
+  VERIFY((is_same<result_of<default_args(char*)>::type, void>::value));
+  VERIFY((is_same<result_of<func_ptr(char, float)>::type, int>::value));
+  VERIFY((is_same<result_of<func_ref(char, float)>::type, int>::value));
+}
+
+int main()
+{
+  test01();
+  return 0;
+}
diff --git a/libstdc++-v3/testsuite/20_util/function_objects/return_types/result_of_neg.cc b/libstdc++-v3/testsuite/20_util/function_objects/return_types/result_of_neg.cc
new file mode 100644 (file)
index 0000000..037a729
--- /dev/null
@@ -0,0 +1,48 @@
+// { dg-options "-std=gnu++0x" }
+// { dg-do compile }
+// Copyright (C) 2008 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 2, 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 COPYING.  If not, write to the Free
+// Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+// USA.
+
+// 20.6.4 function object return types [func.ret]
+#include <functional>
+#include <testsuite_hooks.h>
+
+struct X
+{
+    int i;
+    int f();
+};
+
+void test01()
+{
+  bool test __attribute__((unused)) = true;
+
+  using std::result_of;
+  using std::is_same;
+
+  typedef int X::*pm;
+  typedef int (X::*pmf)();
+  typedef int (*pf)();
+
+  result_of<pmf(X*, int)>::type test2; // { dg-error "here" }
+  // { dg-error "too many arguments to function" "" { target *-*-* } 286 }
+  result_of<pf(int)>::type test3; // { dg-error "here" }
+  // { dg-error "too many arguments to function" "" { target *-*-* } 299 }
+}
+
+// { dg-excess-errors "" }
diff --git a/libstdc++-v3/testsuite/20_util/function_objects/return_types/result_of_ref.cc b/libstdc++-v3/testsuite/20_util/function_objects/return_types/result_of_ref.cc
new file mode 100644 (file)
index 0000000..d3006a6
--- /dev/null
@@ -0,0 +1,49 @@
+// { dg-options "-std=gnu++0x" }
+// Copyright (C) 2008 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 2, 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 COPYING.  If not, write to the Free
+// Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
+// USA.
+
+// 20.6.4 function object return types [func.ret]
+#include <functional>
+#include <testsuite_hooks.h>
+
+struct X
+{
+    int operator()(int&);
+    float operator()(int&&);
+};
+
+void test01()
+{
+  bool test __attribute__((unused)) = true;
+
+  using std::result_of;
+  using std::is_same;
+
+  typedef int (*func_ptr)(int&);
+
+  VERIFY((is_same<result_of<X(int)>::type, float>::value));
+  VERIFY((is_same<result_of<X(int&)>::type, int>::value));
+  VERIFY((is_same<result_of<X(int&&)>::type, float>::value));
+  VERIFY((is_same<result_of<func_ptr(int&)>::type, int>::value));
+}
+
+int main()
+{
+  test01();
+  return 0;
+}
index d948235409b181081ee8202b8b26c9644f34f9c9..80be053a8772d7bd8fcfe821ca4ce4a5a77a659b 100644 (file)
@@ -70,7 +70,7 @@ void test01()
    std::reference_wrapper<functor1>* pr5(0);
 
    // libstdc++/24803
-   // FIXME: verify_return_type((*pr5)(0), double());
+   verify_return_type((*pr5)(0), double());
    verify_return_type((*pr5)(zero), double());
 
    std::reference_wrapper<double (int, char)>* pr1b(0);
@@ -84,6 +84,6 @@ void test01()
    std::reference_wrapper<functor2>* pr5b(0);
 
    // libstdc++/24803
-   // FIXME: verify_return_type((*pr5b)(0,0), double());
+   verify_return_type((*pr5b)(0,0), double());
    verify_return_type((*pr5b)(zero,zero), double());
 }