From a28a65ec257285afa3bdad02e7d769abd27ebacb Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Wed, 5 Nov 2008 02:05:59 +0000 Subject: [PATCH] re PR libstdc++/24803 ([c++0x] reference_wrapper and pointers to member functions) 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 | 13 ++ libstdc++-v3/include/tr1_impl/functional | 161 ++++++++++++++++++ .../return_types/result_of.cc | 76 +++++++++ .../return_types/result_of_neg.cc | 48 ++++++ .../return_types/result_of_ref.cc | 49 ++++++ .../20_util/reference_wrapper/24803.cc | 4 +- 6 files changed, 349 insertions(+), 2 deletions(-) create mode 100644 libstdc++-v3/testsuite/20_util/function_objects/return_types/result_of.cc create mode 100644 libstdc++-v3/testsuite/20_util/function_objects/return_types/result_of_neg.cc create mode 100644 libstdc++-v3/testsuite/20_util/function_objects/return_types/result_of_ref.cc diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 47ffacc35ce..47eaf4936fd 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,16 @@ +2008-11-05 Jonathan Wakely + + 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 * include/bits/locale_facets.tcc (num_get<>::do_get(iter_type, diff --git a/libstdc++-v3/include/tr1_impl/functional b/libstdc++-v3/include/tr1_impl/functional index b819374f92d..6432181bfc0 100644 --- a/libstdc++-v3/include/tr1_impl/functional +++ b/libstdc++-v3/include/tr1_impl/functional @@ -153,6 +153,7 @@ _GLIBCXX_BEGIN_NAMESPACE_TR1 template 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 + struct _Result_of_impl; + + // Helper functions used by _Result_of_impl. + template + struct _Result_of_arg + { + // http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-active.html#904 +#if 0 + static typename conditional::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 + struct _Result_of_lhs + { + static _Tp _S_fwd(); + }; + template + struct _Result_of_lhs<_Tp, false> + { + static decltype( *_Result_of_lhs<_Tp,true>::_S_fwd() ) _S_fwd(); + }; + + // Handle member data pointers. + template + class _Result_of_impl + { + 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 + class _Result_of_impl + { + template + struct _Get_class; + + template + struct _Get_class<_Res (_Class::*)(_Args...)> + { typedef _Class type; }; + template + struct _Get_class<_Res (_Class::*)(_Args...) const> + { typedef _Class type; }; + template + struct _Get_class<_Res (_Class::*)(_Args...) volatile> + { typedef _Class type; }; + template + 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 + class _Result_of_impl + { + // 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 + 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 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 + inline + typename enable_if< + (!is_member_pointer<_Functor>::value + && !is_function<_Functor>::value + && !is_function::type>::value), + typename result_of<_Functor(_Args...)>::type + >::type + __invoke(_Functor& __f, _Args&&... __args) + { + return __f(std::forward<_Args>(__args)...); + } + + template + inline + typename enable_if< + (is_member_pointer<_Functor>::value + && !is_function<_Functor>::value + && !is_function::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 + inline + typename enable_if< + (is_pointer<_Functor>::value + && is_function::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 result_of<_M_func_type(_Args...)>::type operator()(_Args&... __args) const { return __invoke(get(), __args...); } +#else + template + 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 index 00000000000..50f64b67885 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/function_objects/return_types/result_of.cc @@ -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 +#include + +struct nested_result_type +{ + typedef float result_type; + int operator()(); +}; + +struct nested_result_template +{ + template 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::type, int>::value)); + VERIFY((is_same::type, int>::value)); + VERIFY((is_same::type, int>::value)); + VERIFY((is_same::type, char>::value)); + VERIFY((is_same::type, float>::value)); + VERIFY((is_same::type, int>::value)); + VERIFY((is_same::type, void>::value)); + VERIFY((is_same::type, int>::value)); + VERIFY((is_same::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 index 00000000000..037a7291abd --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/function_objects/return_types/result_of_neg.cc @@ -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 +#include + +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::type test2; // { dg-error "here" } + // { dg-error "too many arguments to function" "" { target *-*-* } 286 } + result_of::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 index 00000000000..d3006a6b7f7 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/function_objects/return_types/result_of_ref.cc @@ -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 +#include + +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::type, float>::value)); + VERIFY((is_same::type, int>::value)); + VERIFY((is_same::type, float>::value)); + VERIFY((is_same::type, int>::value)); +} + +int main() +{ + test01(); + return 0; +} diff --git a/libstdc++-v3/testsuite/20_util/reference_wrapper/24803.cc b/libstdc++-v3/testsuite/20_util/reference_wrapper/24803.cc index d948235409b..80be053a877 100644 --- a/libstdc++-v3/testsuite/20_util/reference_wrapper/24803.cc +++ b/libstdc++-v3/testsuite/20_util/reference_wrapper/24803.cc @@ -70,7 +70,7 @@ void test01() std::reference_wrapper* 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* pr1b(0); @@ -84,6 +84,6 @@ void test01() std::reference_wrapper* 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()); } -- 2.30.2