Upstream-Status: Inappropriate [Backport] From 0755fde6008ab7a7ae98f3b4c5967191408431f3 Mon Sep 17 00:00:00 2001 From: redi Date: Sat, 23 Apr 2011 17:51:31 +0000 Subject: [PATCH 173/200] 2011-04-23 Jonathan Wakely PR libstdc++/48521 * include/std/type_traits (result_of): Handle pointer to member. * include/std/functional (__invoke): Likewise. (_Function_to_function_pointer): Remove. (_Reference_wrapper_base): Provide nested types independent of unary_function and binary_function. (reference_wrapper::operator()): DR 2017. (ref(const A&&), cref(const A&&): Define as deleted. * include/std/future (async): Simplify SFINAE and use result_of to support pointer to member. * testsuite/20_util/reference_wrapper/invoke.cc: Test pointer to member. * testsuite/20_util/reference_wrapper/24803.cc: Likewise. * testsuite/20_util/reference_wrapper/typedefs.cc: Test for types instead of derivation from unary_function and binary_function. * testsuite/20_util/reference_wrapper/invoke-2.cc: New. * testsuite/20_util/reference_wrapper/ref_neg.c: New. * testsuite/20_util/reference_wrapper/typedefs-3.c: New. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/gcc-4_6-branch@172901 138bc75d-0d04-0410-961f-82ee72b054a4 index 660e371..57ec506 100644 --- a/libstdc++-v3/include/std/functional +++ b/libstdc++-v3/include/std/functional @@ -212,19 +212,6 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type) static const bool value = sizeof(__test((_Tp*)0)) == 1; }; - /// Turns a function type into a function pointer type - template::value> - struct _Function_to_function_pointer - { - typedef _Tp type; - }; - - template - struct _Function_to_function_pointer<_Tp, true> - { - typedef _Tp* type; - }; - /** * Invoke a function object, which may be either a member pointer or a * function object. The first parameter will tell which. @@ -235,20 +222,33 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type) (!is_member_pointer<_Functor>::value && !is_function<_Functor>::value && !is_function::type>::value), - typename result_of<_Functor(_Args...)>::type + 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 + typename result_of<_Functor(_Args&&...)>::type >::type __invoke(_Functor __f, _Args&&... __args) { @@ -263,40 +263,43 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type) template struct _Reference_wrapper_base_impl; - // Not a unary_function or binary_function, so try a weak result type. + // None of the nested argument types. template struct _Reference_wrapper_base_impl : _Weak_result_type<_Tp> { }; - // unary_function but not binary_function + // Nested argument_type only. template struct _Reference_wrapper_base_impl - : unary_function - { }; + : _Weak_result_type<_Tp> + { + typedef typename _Tp::argument_type argument_type; + }; - // binary_function but not unary_function + // Nested first_argument_type and second_argument_type only. template struct _Reference_wrapper_base_impl - : binary_function - { }; + : _Weak_result_type<_Tp> + { + typedef typename _Tp::first_argument_type first_argument_type; + typedef typename _Tp::second_argument_type second_argument_type; + }; - // Both unary_function and binary_function. Import result_type to - // avoid conflicts. + // All the nested argument types. template struct _Reference_wrapper_base_impl - : unary_function, - binary_function + : _Weak_result_type<_Tp> { - typedef typename _Tp::result_type result_type; + typedef typename _Tp::argument_type argument_type; + typedef typename _Tp::first_argument_type first_argument_type; + typedef typename _Tp::second_argument_type second_argument_type; }; + _GLIBCXX_HAS_NESTED_TYPE(argument_type) + _GLIBCXX_HAS_NESTED_TYPE(first_argument_type) + _GLIBCXX_HAS_NESTED_TYPE(second_argument_type) + /** * Derives from unary_function or binary_function when it * can. Specializations handle all of the easy cases. The primary @@ -306,8 +309,9 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type) template struct _Reference_wrapper_base : _Reference_wrapper_base_impl< - _Derives_from_unary_function<_Tp>::value, - _Derives_from_binary_function<_Tp>::value, + __has_argument_type<_Tp>::value, + __has_first_argument_type<_Tp>::value + && __has_second_argument_type<_Tp>::value, _Tp> { }; @@ -422,12 +426,8 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type) class reference_wrapper : public _Reference_wrapper_base::type> { - // If _Tp is a function type, we can't form result_of<_Tp(...)>, - // so turn it into a function pointer type. - typedef typename _Function_to_function_pointer<_Tp>::type - _M_func_type; - _Tp* _M_data; + public: typedef _Tp type; @@ -456,7 +456,7 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type) { return *_M_data; } template - typename result_of<_M_func_type(_Args...)>::type + typename result_of<_Tp&(_Args&&...)>::type operator()(_Args&&... __args) const { return __invoke(get(), std::forward<_Args>(__args)...); @@ -476,6 +476,12 @@ _GLIBCXX_HAS_NESTED_TYPE(result_type) cref(const _Tp& __t) { return reference_wrapper(__t); } + template + void ref(const _Tp&&) = delete; + + template + void cref(const _Tp&&) = delete; + /// Partial specialization. template inline reference_wrapper<_Tp> diff --git a/libstdc++-v3/include/std/future b/libstdc++-v3/include/std/future index 17d46db..970ce76 100644 --- a/libstdc++-v3/include/std/future +++ b/libstdc++-v3/include/std/future @@ -142,11 +142,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION future::type> async(launch __policy, _Fn&& __fn, _Args&&... __args); + template + struct __async_sfinae_helper + { + typedef future::type> type; + }; + + template + struct __async_sfinae_helper + { }; + template typename - enable_if::type, launch>::value, - future()(std::declval<_Args>()...))> - >::type + __async_sfinae_helper::type, _Fn, _Args...>::type async(_Fn&& __fn, _Args&&... __args); #if defined(_GLIBCXX_HAS_GTHREADS) && defined(_GLIBCXX_USE_C99_STDINT_TR1) \ @@ -1366,9 +1374,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION /// async, potential overload template inline typename - enable_if::type, launch>::value, - future()(std::declval<_Args>()...))> - >::type + __async_sfinae_helper::type, _Fn, _Args...>::type async(_Fn&& __fn, _Args&&... __args) { return async(launch::any, std::forward<_Fn>(__fn), diff --git a/libstdc++-v3/include/std/type_traits b/libstdc++-v3/include/std/type_traits index f5d867b..2361152 100644 --- a/libstdc++-v3/include/std/type_traits +++ b/libstdc++-v3/include/std/type_traits @@ -1140,12 +1140,92 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION template class result_of; + template + struct _Result_of_memobj; + + template + struct _Result_of_memobj<_Res _Class::*, _Arg> + { + private: + typedef _Res _Class::* _Func; + + template + static _Tp _S_get(const _Class&); + template + static decltype(*std::declval<_Tp>()) _S_get(...); + + public: + typedef + decltype(_S_get<_Arg>(std::declval<_Arg>()).*std::declval<_Func>()) + __type; + }; + + template + struct _Result_of_memfun; + + template + struct _Result_of_memfun<_Res _Class::*, _Arg, _Args...> + { + private: + typedef _Res _Class::* _Func; + + template + static _Tp _S_get(const _Class&); + template + static decltype(*std::declval<_Tp>()) _S_get(...); + + public: + typedef + decltype((_S_get<_Arg>(std::declval<_Arg>()).*std::declval<_Func>()) + (std::declval<_Args>()...) ) + __type; + }; + + template + struct _Result_of_impl; + template - struct result_of<_Functor(_ArgTypes...)> + struct _Result_of_impl { typedef decltype( std::declval<_Functor>()(std::declval<_ArgTypes>()...) ) - type; + __type; + }; + + template + struct _Result_of_impl + : _Result_of_memobj::type, _Arg> + { + typedef typename _Result_of_memobj< + typename remove_reference<_MemPtr>::type, _Arg>::__type + __type; + }; + + template + struct _Result_of_impl + : _Result_of_memfun::type, _Arg, + _ArgTypes...> + { + typedef typename _Result_of_memfun< + typename remove_reference<_MemPtr>::type, _Arg, _ArgTypes...>::__type + __type; + }; + + template + struct result_of<_Functor(_ArgTypes...)> + : _Result_of_impl::type >::value, + is_member_function_pointer< + typename remove_reference<_Functor>::type >::value, + _Functor, _ArgTypes...> + { + typedef typename _Result_of_impl< + is_member_object_pointer< + typename remove_reference<_Functor>::type >::value, + is_member_function_pointer< + typename remove_reference<_Functor>::type >::value, + _Functor, _ArgTypes...>::__type + type; }; /** diff --git a/libstdc++-v3/testsuite/20_util/reference_wrapper/24803.cc b/libstdc++-v3/testsuite/20_util/reference_wrapper/24803.cc index 598c5c8..4bf6148 100644 --- a/libstdc++-v3/testsuite/20_util/reference_wrapper/24803.cc +++ b/libstdc++-v3/testsuite/20_util/reference_wrapper/24803.cc @@ -1,7 +1,7 @@ // { dg-options "-std=gnu++0x" } // { dg-do compile } -// Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc. +// Copyright (C) 2008, 2009, 2010, 2011 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 @@ -46,12 +46,18 @@ void verify_return_type(T, T) void test01() { + test_type* null_tt = 0; + const test_type* null_ttc = 0; int zero; std::reference_wrapper* pr1(0); verify_return_type((*pr1)(0), double()); std::reference_wrapper* pr2(0); verify_return_type((*pr2)(0), double()); + std::reference_wrapper* pr3(0); + verify_return_type((*pr3)(null_tt), int()); + std::reference_wrapper* pr4(0); + verify_return_type((*pr4)(null_ttc), int()); std::reference_wrapper* pr5(0); // libstdc++/24803 @@ -62,6 +68,10 @@ void test01() verify_return_type((*pr1b)(0, 0), double()); std::reference_wrapper* pr2b(0); verify_return_type((*pr2b)(0, 0), double()); + std::reference_wrapper* pr3b(0); + verify_return_type((*pr3b)(null_tt,zero), int()); + std::reference_wrapper* pr4b(0); + verify_return_type((*pr4b)(null_ttc), int()); std::reference_wrapper* pr5b(0); // libstdc++/24803 diff --git a/libstdc++-v3/testsuite/20_util/reference_wrapper/invoke-2.cc b/libstdc++-v3/testsuite/20_util/reference_wrapper/invoke-2.cc new file mode 100644 index 0000000..bd9aeb2 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/reference_wrapper/invoke-2.cc @@ -0,0 +1,47 @@ +// { dg-options "-std=gnu++0x" } +// { dg-do compile} +// Copyright (C) 2011 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 + +struct X +{ + int f(int) { return 0; } + int i; +}; + +void test01() +{ + typedef int (X::*mfp)(int); + typedef int X::*mp; + mfp m = &X::f; + mp m2 = &X::i; + X x = { }; + std::ref(m)(x, 1); + std::ref(m)(&x, 1); + int& i1 = std::ref(m2)(x); + int& i2 = std::ref(m2)(&x); +} + +int main() +{ + test01(); + return 0; +} diff --git a/libstdc++-v3/testsuite/20_util/reference_wrapper/invoke.cc b/libstdc++-v3/testsuite/20_util/reference_wrapper/invoke.cc index b371f1c..7b694c7 100644 --- a/libstdc++-v3/testsuite/20_util/reference_wrapper/invoke.cc +++ b/libstdc++-v3/testsuite/20_util/reference_wrapper/invoke.cc @@ -1,6 +1,6 @@ // { dg-options "-std=gnu++0x" } -// Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc. +// Copyright (C) 2008, 2009, 2010, 2011 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 @@ -36,6 +36,7 @@ struct X int foo_c(float x) const { return truncate_float(x); } int foo_v(float x) volatile { return truncate_float(x); } int foo_cv(float x) const volatile { return truncate_float(x); } + int foo_varargs(float x, ...) { return truncate_float(x); } int operator()(float x) { @@ -69,6 +70,13 @@ void test01() ::get_seventeen get_sev; ::X x; + ::X* xp = &x; + int (::X::* p_foo)(float) = &::X::foo; + int (::X::* p_foo_c)(float) const = &::X::foo_c; + int (::X::* p_foo_v)(float) volatile = &::X::foo_v; + int (::X::* p_foo_cv)(float) const volatile = &::X::foo_cv; + int (::X::* p_foo_varargs)(float, ...) = &::X::foo_varargs; + int ::X::* p_bar = &::X::bar; const float pi = 3.14; @@ -77,8 +85,26 @@ void test01() VERIFY(ref(seventeen)() == 17); // Function pointers - VERIFY(cref(&truncate_float)(pi) == 3); - VERIFY(cref(&seventeen)() == 17); + VERIFY(cref(truncate_float)(pi) == 3); + VERIFY(cref(seventeen)() == 17); + + // Member function pointers + VERIFY(ref(p_foo)(x, pi) == 3); + VERIFY(ref(p_foo)(xp, pi) == 3); + VERIFY(ref(p_foo_c)(x, pi) == 3); + VERIFY(ref(p_foo_c)(xp, pi) == 3); + VERIFY(ref(p_foo_v)(x, pi) == 3); + VERIFY(ref(p_foo_v)(xp, pi) == 3); + VERIFY(ref(p_foo_cv)(x, pi) == 3); + VERIFY(ref(p_foo_cv)(xp, pi) == 3); + // VERIFY(ref(p_foo_varargs)(x, pi) == 3); + // VERIFY(ref(p_foo_varargs)(xp, pi, 1, 1) == 3); + // VERIFY(ref(p_foo_varargs)(x, pi, 1, 1) == 3); + // VERIFY(ref(p_foo_varargs)(xp, pi) == 3); + + // Member data pointers + VERIFY(ref(p_bar)(x) == 17); + VERIFY(ref(p_bar)(xp) == 17); // Function objects VERIFY(ref(get_sev)() == 17); diff --git a/libstdc++-v3/testsuite/20_util/reference_wrapper/ref_neg.cc b/libstdc++-v3/testsuite/20_util/reference_wrapper/ref_neg.cc new file mode 100644 index 0000000..947a9b0 --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/reference_wrapper/ref_neg.cc @@ -0,0 +1,44 @@ +// Copyright (C) 2011 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 +// . + +// 20.8.3 Class template reference_wrapper + +// { dg-do compile } +// { dg-options "-std=gnu++0x" } + +#include + +struct X { }; +X rval(); +X&& rvalref(); + +void test01() +{ + std::ref(1); // { dg-error "deleted" } + std::cref(1); // { dg-error "deleted" } + std::ref( int() ); // { dg-error "deleted" } + std::cref( int() ); // { dg-error "deleted" } + std::ref(rval()); // { dg-error "deleted" } + std::cref(rvalref()); // { dg-error "deleted" } +} + +int main() +{ + test02(); +} + +// { dg-excess-errors "" } diff --git a/libstdc++-v3/testsuite/20_util/reference_wrapper/typedefs-3.cc b/libstdc++-v3/testsuite/20_util/reference_wrapper/typedefs-3.cc new file mode 100644 index 0000000..2fea52e --- /dev/null +++ b/libstdc++-v3/testsuite/20_util/reference_wrapper/typedefs-3.cc @@ -0,0 +1,148 @@ +// { dg-options "-std=gnu++0x" } +// { dg-do compile } + +// Copyright (C) 2011 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 +// . + +#include +#include + +struct S { }; + +struct S0 +{ + typedef int argument_type; +}; + +struct S1 +{ + typedef float first_argument_type; +}; + +struct S2 +{ + typedef char second_argument_type; +}; + +struct S01 : S0, S1 { }; +struct S02 : S0, S2 { }; +struct S12 : S1, S2 { }; + +struct S012 : S0, S1, S2 { }; + +using std::__sfinae_types; +using std::integral_constant; +using std::remove_cv; + +_GLIBCXX_HAS_NESTED_TYPE(argument_type) +_GLIBCXX_HAS_NESTED_TYPE(first_argument_type) +_GLIBCXX_HAS_NESTED_TYPE(second_argument_type) + +template + struct has_arg_type : __has_argument_type + { }; + +template + struct has_1st_arg_type : __has_first_argument_type + { }; + +template + struct has_2nd_arg_type : __has_second_argument_type + { }; + +template::value> +struct test_arg_type +{ + static_assert( !has_arg_type>::value, + "reference_wrapper has no nested argument_type"); +}; + +template +struct test_arg_type +{ + typedef std::reference_wrapper ref; + + static_assert( has_arg_type::value, + "reference_wrapper has nested argument_type"); + + static_assert( + std::is_same< typename T::argument_type, + typename ref::argument_type >::value, + "reference_wrapper has the correct argument_type"); +}; + +template::value && has_2nd_arg_type::value> +struct test_1st_2nd_arg_types +{ + typedef std::reference_wrapper ref; + + static_assert( !has_1st_arg_type::value, + "reference_wrapper has no nested first_argument_type"); + + static_assert( !has_2nd_arg_type::value, + "reference_wrapper has no nested second_argument_type"); +}; + +template +struct test_1st_2nd_arg_types +{ + typedef std::reference_wrapper ref; + + static_assert( has_1st_arg_type::value, + "reference_wrapper has nested first_argument_type"); + + static_assert( has_2nd_arg_type::value, + "reference_wrapper has nested second_argument_type"); + + static_assert( + std::is_same< typename T::first_argument_type, + typename ref::first_argument_type>::value, + "reference_wrapper has correct first_argument_type"); + + static_assert( + std::is_same< typename T::second_argument_type, + typename ref::second_argument_type>::value, + "reference_wrapper has correct second_argument_type"); +}; + + +template + void test() + { + test_arg_type t; + test_arg_type tc; + test_arg_type tv; + test_arg_type tcv; + test_1st_2nd_arg_types t12; + test_1st_2nd_arg_types t12c; + test_1st_2nd_arg_types t12v; + test_1st_2nd_arg_types t12cv; + } + +int main() +{ + test(); + test(); + test(); + test(); + test(); + test(); + test(); + test(); +} + diff --git a/libstdc++-v3/testsuite/20_util/reference_wrapper/typedefs.cc b/libstdc++-v3/testsuite/20_util/reference_wrapper/typedefs.cc index 56ee29e..815700f 100644 --- a/libstdc++-v3/testsuite/20_util/reference_wrapper/typedefs.cc +++ b/libstdc++-v3/testsuite/20_util/reference_wrapper/typedefs.cc @@ -1,6 +1,7 @@ +// { dg-do compile } // { dg-options "-std=gnu++0x" } -// Copyright (C) 2008, 2009 Free Software Foundation, Inc. +// Copyright (C) 2008, 2009, 2010, 2011 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 @@ -19,10 +20,6 @@ #include #include -#include -#include - -using namespace __gnu_test; struct X {}; @@ -41,43 +38,18 @@ struct derives_unary_binary void test01() { - bool test __attribute__((unused)) = true; - using std::reference_wrapper; using std::is_same; - using std::is_convertible; - using std::unary_function; - using std::binary_function; // Check result_type typedef - VERIFY((is_same::result_type, int>::value)); - VERIFY((is_same::result_type, int>::value)); - VERIFY((is_same::result_type, int>::value)); - VERIFY((is_same::result_type, int>::value)); - VERIFY((is_same::result_type, int>::value)); - VERIFY((is_same::result_type, int>::value)); - VERIFY((is_same::result_type, int>::value)); - VERIFY((is_same::result_type, int>::value)); - - // Check derivation from unary_function - VERIFY((is_convertible*, unary_function*>::value)); - VERIFY((is_convertible*, unary_function*>::value)); - VERIFY((is_convertible*, unary_function*>::value)); - VERIFY((is_convertible*, unary_function*>::value)); - VERIFY((is_convertible*, unary_function< ::X*, int>*>::value)); - VERIFY((is_convertible*, unary_function*>::value)); - VERIFY((is_convertible*, unary_function*>::value)); - VERIFY((is_convertible*, unary_function*>::value)); - - // Check derivation from binary_function - VERIFY((is_convertible*, binary_function*>::value)); - VERIFY((is_convertible*, binary_function*>::value)); - VERIFY((is_convertible*, binary_function*>::value)); - VERIFY((is_convertible*, binary_function*>::value)); - VERIFY((is_convertible*, binary_function< ::X*, float, int>*>::value)); - VERIFY((is_convertible*, binary_function*>::value)); - VERIFY((is_convertible*, binary_function*>::value)); - VERIFY((is_convertible*, binary_function*>::value)); + static_assert( is_same::result_type, int>::value, "has result_type" ); + static_assert( is_same::result_type, int>::value, "has result_type" ); + static_assert( is_same::result_type, int>::value, "has result_type" ); + static_assert( is_same::result_type, int>::value, "has result_type" ); + static_assert( is_same::result_type, int>::value, "has result_type" ); + static_assert( is_same::result_type, int>::value, "has result_type" ); + static_assert( is_same::result_type, int>::value, "has result_type" ); + static_assert( is_same::result_type, int>::value, "has result_type" ); } int main() -- 1.7.0.4