From de1d079440179287ff154a66218b2f2fd41a9acf Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Fri, 14 Oct 2016 20:04:56 +0100 Subject: [PATCH] Make std::bind use std::invoke * include/std/functional (_Mu, _Mu): Simplify forwarding from tuple of references. (_Maybe_wrap_member_pointer): Remove. (_Bind::__call, _Bind::__call_c, _Bind::__call_v, _Bind::__call_c_v): Use std::__invoke. (_Bind::_Mu_type, _Bind::_Res_type_impl, _Bind::_Res_type) (_Bind::__dependent, _Bind::_Res_type_cv): New helpers to simplify return type deduction. (_Bind::operator(), _Bind::operator() const): Use new helpers. (_Bind::operator() volatile, _Bind::operator() const volatile): Likewise. Add deprecated attribute for C++17 mode. (_Bind_result::__call): Use std::__invoke. (_Bind_result::operator() volatile) (_Bind_result::operator() const volatile): Add deprecated attribute. (_Bind_helper::__maybe_type, _Bindres_helper::__maybe_type): Remove. (_Bind_helper, _Bindres_helper): Don't use _Maybe_wrap_member_pointer. (bind, bind): Don't use __maybe_type. * src/c++11/compatibility-thread-c++0x.cc (_Maybe_wrap_member_pointer): Define here for compatibility symbols. * testsuite/20_util/bind/68912.cc: Don't test volatile-qualification in C++17 mode. * testsuite/20_util/bind/cv_quals.cc: Likewise. * testsuite/20_util/bind/cv_quals_2.cc: Likewise. From-SVN: r241178 --- libstdc++-v3/ChangeLog | 24 +++ libstdc++-v3/include/std/functional | 168 ++++++++---------- .../src/c++11/compatibility-thread-c++0x.cc | 13 ++ libstdc++-v3/testsuite/20_util/bind/68912.cc | 2 + .../testsuite/20_util/bind/cv_quals.cc | 8 + .../testsuite/20_util/bind/cv_quals_2.cc | 2 + 6 files changed, 119 insertions(+), 98 deletions(-) diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 7a3fdaf29f1..2ce59323b07 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,5 +1,29 @@ 2016-10-14 Jonathan Wakely + * include/std/functional (_Mu, _Mu): + Simplify forwarding from tuple of references. + (_Maybe_wrap_member_pointer): Remove. + (_Bind::__call, _Bind::__call_c, _Bind::__call_v, _Bind::__call_c_v): + Use std::__invoke. + (_Bind::_Mu_type, _Bind::_Res_type_impl, _Bind::_Res_type) + (_Bind::__dependent, _Bind::_Res_type_cv): New helpers to simplify + return type deduction. + (_Bind::operator(), _Bind::operator() const): Use new helpers. + (_Bind::operator() volatile, _Bind::operator() const volatile): + Likewise. Add deprecated attribute for C++17 mode. + (_Bind_result::__call): Use std::__invoke. + (_Bind_result::operator() volatile) + (_Bind_result::operator() const volatile): Add deprecated attribute. + (_Bind_helper::__maybe_type, _Bindres_helper::__maybe_type): Remove. + (_Bind_helper, _Bindres_helper): Don't use _Maybe_wrap_member_pointer. + (bind, bind): Don't use __maybe_type. + * src/c++11/compatibility-thread-c++0x.cc + (_Maybe_wrap_member_pointer): Define here for compatibility symbols. + * testsuite/20_util/bind/68912.cc: Don't test volatile-qualification + in C++17 mode. + * testsuite/20_util/bind/cv_quals.cc: Likewise. + * testsuite/20_util/bind/cv_quals_2.cc: Likewise. + * include/std/scoped_allocator (scoped_allocator_adaptor): Forward piecewise construction arguments as tuples of references, to avoid copies (related to LWG 2511). diff --git a/libstdc++-v3/include/std/functional b/libstdc++-v3/include/std/functional index d39b519fb77..ad67a1d6dc0 100644 --- a/libstdc++-v3/include/std/functional +++ b/libstdc++-v3/include/std/functional @@ -742,7 +742,7 @@ _GLIBCXX_MEM_FN_TRAITS(&&, false_type, true_type) const _Index_tuple<_Indexes...>&) const volatile -> decltype(__arg(declval<_Args>()...)) { - return __arg(std::forward<_Args>(std::get<_Indexes>(__tuple))...); + return __arg(std::get<_Indexes>(std::move(__tuple))...); } }; @@ -759,10 +759,8 @@ _GLIBCXX_MEM_FN_TRAITS(&&, false_type, true_type) _Safe_tuple_element_t<(is_placeholder<_Arg>::value - 1), _Tuple>&& operator()(const volatile _Arg&, _Tuple& __tuple) const volatile { - using __type - = __tuple_element_t<(is_placeholder<_Arg>::value - 1), _Tuple>; - return std::forward<__type>( - ::std::get<(is_placeholder<_Arg>::value - 1)>(__tuple)); + return + ::std::get<(is_placeholder<_Arg>::value - 1)>(std::move(__tuple)); } }; @@ -781,50 +779,6 @@ _GLIBCXX_MEM_FN_TRAITS(&&, false_type, true_type) { return std::forward<_CVArg>(__arg); } }; - /** - * Maps member pointers into instances of _Mem_fn but leaves all - * other function objects untouched. Used by std::bind(). The - * primary template handles the non-member-pointer case. - */ - template - struct _Maybe_wrap_member_pointer - { - typedef _Tp type; - - static constexpr const _Tp& - __do_wrap(const _Tp& __x) - { return __x; } - - static constexpr _Tp&& - __do_wrap(_Tp&& __x) - { return static_cast<_Tp&&>(__x); } - }; - - /** - * Maps member pointers into instances of _Mem_fn but leaves all - * other function objects untouched. Used by std::bind(). This - * partial specialization handles the member pointer case. - */ - template - struct _Maybe_wrap_member_pointer<_Tp _Class::*> - { - typedef _Mem_fn<_Tp _Class::*> type; - - static constexpr type - __do_wrap(_Tp _Class::* __pm) - { return type(__pm); } - }; - - // Specialization needed to prevent "forming reference to void" errors when - // bind() is called, because argument deduction instantiates - // _Maybe_wrap_member_pointer outside the immediate context where - // SFINAE applies. - template<> - struct _Maybe_wrap_member_pointer - { - typedef void type; - }; - // std::get for volatile-qualified tuples template inline auto @@ -858,8 +812,9 @@ _GLIBCXX_MEM_FN_TRAITS(&&, false_type, true_type) _Result __call(tuple<_Args...>&& __args, _Index_tuple<_Indexes...>) { - return _M_f(_Mu<_Bound_args>() - (std::get<_Indexes>(_M_bound_args), __args)...); + return std::__invoke(_M_f, + _Mu<_Bound_args>()(std::get<_Indexes>(_M_bound_args), __args)... + ); } // Call as const @@ -867,8 +822,9 @@ _GLIBCXX_MEM_FN_TRAITS(&&, false_type, true_type) _Result __call_c(tuple<_Args...>&& __args, _Index_tuple<_Indexes...>) const { - return _M_f(_Mu<_Bound_args>() - (std::get<_Indexes>(_M_bound_args), __args)...); + return std::__invoke(_M_f, + _Mu<_Bound_args>()(std::get<_Indexes>(_M_bound_args), __args)... + ); } // Call as volatile @@ -877,8 +833,9 @@ _GLIBCXX_MEM_FN_TRAITS(&&, false_type, true_type) __call_v(tuple<_Args...>&& __args, _Index_tuple<_Indexes...>) volatile { - return _M_f(_Mu<_Bound_args>() - (__volget<_Indexes>(_M_bound_args), __args)...); + return std::__invoke(_M_f, + _Mu<_Bound_args>()(__volget<_Indexes>(_M_bound_args), __args)... + ); } // Call as const volatile @@ -887,10 +844,33 @@ _GLIBCXX_MEM_FN_TRAITS(&&, false_type, true_type) __call_c_v(tuple<_Args...>&& __args, _Index_tuple<_Indexes...>) const volatile { - return _M_f(_Mu<_Bound_args>() - (__volget<_Indexes>(_M_bound_args), __args)...); + return std::__invoke(_M_f, + _Mu<_Bound_args>()(__volget<_Indexes>(_M_bound_args), __args)... + ); } + template + using _Mu_type = decltype( + _Mu::type>()( + std::declval<_BoundArg&>(), std::declval<_CallArgs&>()) ); + + template + using _Res_type_impl + = typename result_of< _Fn&(_Mu_type<_BArgs, _CallArgs>...) >::type; + + template + using _Res_type = _Res_type_impl<_Functor, _CallArgs, _Bound_args...>; + + template + using __dependent = typename + enable_if::value+1), _Functor>::type; + + template class __cv_quals> + using _Res_type_cv = _Res_type_impl< + typename __cv_quals<__dependent<_CallArgs>>::type, + _CallArgs, + typename __cv_quals<_Bound_args>::type...>; + public: template explicit _Bind(const _Functor& __f, _Args&&... __args) @@ -909,10 +889,8 @@ _GLIBCXX_MEM_FN_TRAITS(&&, false_type, true_type) { } // Call unqualified - template()( - _Mu<_Bound_args>()( std::declval<_Bound_args&>(), - std::declval&>() )... ) )> + template>> _Result operator()(_Args&&... __args) { @@ -922,11 +900,8 @@ _GLIBCXX_MEM_FN_TRAITS(&&, false_type, true_type) } // Call as const - template= 0), - typename add_const<_Functor>::type&>::type>()( - _Mu<_Bound_args>()( std::declval(), - std::declval&>() )... ) )> + template, add_const>> _Result operator()(_Args&&... __args) const { @@ -935,12 +910,16 @@ _GLIBCXX_MEM_FN_TRAITS(&&, false_type, true_type) _Bound_indexes()); } +#if __cplusplus > 201402L +# define _GLIBCXX_DEPR_BIND \ + [[deprecated("std::bind does not support volatile in C++17")]] +#else +# define _GLIBCXX_DEPR_BIND +#endif // Call as volatile - template= 0), - typename add_volatile<_Functor>::type&>::type>()( - _Mu<_Bound_args>()( std::declval(), - std::declval&>() )... ) )> + template, add_volatile>> + _GLIBCXX_DEPR_BIND _Result operator()(_Args&&... __args) volatile { @@ -950,11 +929,9 @@ _GLIBCXX_MEM_FN_TRAITS(&&, false_type, true_type) } // Call as const volatile - template= 0), - typename add_cv<_Functor>::type&>::type>()( - _Mu<_Bound_args>()( std::declval(), - std::declval&>() )... ) )> + template, add_cv>> + _GLIBCXX_DEPR_BIND _Result operator()(_Args&&... __args) const volatile { @@ -991,7 +968,7 @@ _GLIBCXX_MEM_FN_TRAITS(&&, false_type, true_type) __disable_if_void<_Res> __call(tuple<_Args...>&& __args, _Index_tuple<_Indexes...>) { - return _M_f(_Mu<_Bound_args>() + return std::__invoke(_M_f, _Mu<_Bound_args>() (std::get<_Indexes>(_M_bound_args), __args)...); } @@ -1000,7 +977,7 @@ _GLIBCXX_MEM_FN_TRAITS(&&, false_type, true_type) __enable_if_void<_Res> __call(tuple<_Args...>&& __args, _Index_tuple<_Indexes...>) { - _M_f(_Mu<_Bound_args>() + std::__invoke(_M_f, _Mu<_Bound_args>() (std::get<_Indexes>(_M_bound_args), __args)...); } @@ -1009,7 +986,7 @@ _GLIBCXX_MEM_FN_TRAITS(&&, false_type, true_type) __disable_if_void<_Res> __call(tuple<_Args...>&& __args, _Index_tuple<_Indexes...>) const { - return _M_f(_Mu<_Bound_args>() + return std::__invoke(_M_f, _Mu<_Bound_args>() (std::get<_Indexes>(_M_bound_args), __args)...); } @@ -1018,7 +995,7 @@ _GLIBCXX_MEM_FN_TRAITS(&&, false_type, true_type) __enable_if_void<_Res> __call(tuple<_Args...>&& __args, _Index_tuple<_Indexes...>) const { - _M_f(_Mu<_Bound_args>() + std::__invoke(_M_f, _Mu<_Bound_args>() (std::get<_Indexes>(_M_bound_args), __args)...); } @@ -1027,7 +1004,7 @@ _GLIBCXX_MEM_FN_TRAITS(&&, false_type, true_type) __disable_if_void<_Res> __call(tuple<_Args...>&& __args, _Index_tuple<_Indexes...>) volatile { - return _M_f(_Mu<_Bound_args>() + return std::__invoke(_M_f, _Mu<_Bound_args>() (__volget<_Indexes>(_M_bound_args), __args)...); } @@ -1036,7 +1013,7 @@ _GLIBCXX_MEM_FN_TRAITS(&&, false_type, true_type) __enable_if_void<_Res> __call(tuple<_Args...>&& __args, _Index_tuple<_Indexes...>) volatile { - _M_f(_Mu<_Bound_args>() + std::__invoke(_M_f, _Mu<_Bound_args>() (__volget<_Indexes>(_M_bound_args), __args)...); } @@ -1046,7 +1023,7 @@ _GLIBCXX_MEM_FN_TRAITS(&&, false_type, true_type) __call(tuple<_Args...>&& __args, _Index_tuple<_Indexes...>) const volatile { - return _M_f(_Mu<_Bound_args>() + return std::__invoke(_M_f, _Mu<_Bound_args>() (__volget<_Indexes>(_M_bound_args), __args)...); } @@ -1056,7 +1033,7 @@ _GLIBCXX_MEM_FN_TRAITS(&&, false_type, true_type) __call(tuple<_Args...>&& __args, _Index_tuple<_Indexes...>) const volatile { - _M_f(_Mu<_Bound_args>() + std::__invoke(_M_f, _Mu<_Bound_args>() (__volget<_Indexes>(_M_bound_args), __args)...); } @@ -1101,6 +1078,7 @@ _GLIBCXX_MEM_FN_TRAITS(&&, false_type, true_type) // Call as volatile template + _GLIBCXX_DEPR_BIND result_type operator()(_Args&&... __args) volatile { @@ -1111,6 +1089,7 @@ _GLIBCXX_MEM_FN_TRAITS(&&, false_type, true_type) // Call as const volatile template + _GLIBCXX_DEPR_BIND result_type operator()(_Args&&... __args) const volatile { @@ -1119,6 +1098,7 @@ _GLIBCXX_MEM_FN_TRAITS(&&, false_type, true_type) _Bound_indexes()); } }; +#undef _GLIBCXX_DEPR_BIND /** * @brief Class template _Bind is always a bind expression. @@ -1222,9 +1202,7 @@ _GLIBCXX_MEM_FN_TRAITS(&&, false_type, true_type) struct _Bind_helper : _Bind_check_arity::type, _BoundArgs...> { - typedef _Maybe_wrap_member_pointer::type> - __maybe_type; - typedef typename __maybe_type::type __func_type; + typedef typename decay<_Func>::type __func_type; typedef _Bind<__func_type(typename decay<_BoundArgs>::type...)> type; }; @@ -1245,19 +1223,15 @@ _GLIBCXX_MEM_FN_TRAITS(&&, false_type, true_type) bind(_Func&& __f, _BoundArgs&&... __args) { typedef _Bind_helper __helper_type; - typedef typename __helper_type::__maybe_type __maybe_type; - typedef typename __helper_type::type __result_type; - return __result_type(__maybe_type::__do_wrap(std::forward<_Func>(__f)), - std::forward<_BoundArgs>(__args)...); + return typename __helper_type::type(std::forward<_Func>(__f), + std::forward<_BoundArgs>(__args)...); } template struct _Bindres_helper : _Bind_check_arity::type, _BoundArgs...> { - typedef _Maybe_wrap_member_pointer::type> - __maybe_type; - typedef typename __maybe_type::type __functor_type; + typedef typename decay<_Func>::type __functor_type; typedef _Bind_result<_Result, __functor_type(typename decay<_BoundArgs>::type...)> type; @@ -1273,10 +1247,8 @@ _GLIBCXX_MEM_FN_TRAITS(&&, false_type, true_type) bind(_Func&& __f, _BoundArgs&&... __args) { typedef _Bindres_helper<_Result, _Func, _BoundArgs...> __helper_type; - typedef typename __helper_type::__maybe_type __maybe_type; - typedef typename __helper_type::type __result_type; - return __result_type(__maybe_type::__do_wrap(std::forward<_Func>(__f)), - std::forward<_BoundArgs>(__args)...); + return typename __helper_type::type(std::forward<_Func>(__f), + std::forward<_BoundArgs>(__args)...); } /** diff --git a/libstdc++-v3/src/c++11/compatibility-thread-c++0x.cc b/libstdc++-v3/src/c++11/compatibility-thread-c++0x.cc index 5ca2da8d22e..066b08b77de 100644 --- a/libstdc++-v3/src/c++11/compatibility-thread-c++0x.cc +++ b/libstdc++-v3/src/c++11/compatibility-thread-c++0x.cc @@ -116,6 +116,19 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // Replaced with inline definition in gcc-4.8.0 __future_base::_Async_state_common::~_Async_state_common() { _M_join(); } + template + struct _Maybe_wrap_member_pointer; + + template + struct _Maybe_wrap_member_pointer<_Tp _Class::*> + { + typedef _Mem_fn<_Tp _Class::*> type; + + static constexpr type + __do_wrap(_Tp _Class::* __pm) + { return type(__pm); } + }; + template struct _Bind_simple; diff --git a/libstdc++-v3/testsuite/20_util/bind/68912.cc b/libstdc++-v3/testsuite/20_util/bind/68912.cc index 7d191411db1..a32b44be0ad 100644 --- a/libstdc++-v3/testsuite/20_util/bind/68912.cc +++ b/libstdc++-v3/testsuite/20_util/bind/68912.cc @@ -45,8 +45,10 @@ void test01() A res = bound(1.0); const auto bound_c = bound; B res_c = bound_c(1.0); +#if __cplusplus <= 201402L volatile auto bound_v = bound; C res_v = bound_v(1.0); volatile const auto bound_cv = bound; D res_cv = bound_cv(1.0); +#endif } diff --git a/libstdc++-v3/testsuite/20_util/bind/cv_quals.cc b/libstdc++-v3/testsuite/20_util/bind/cv_quals.cc index ebf654fd268..5165f87b49a 100644 --- a/libstdc++-v3/testsuite/20_util/bind/cv_quals.cc +++ b/libstdc++-v3/testsuite/20_util/bind/cv_quals.cc @@ -48,11 +48,13 @@ void test01() const auto b1 = std::bind(X()); VERIFY( b1() == 1 ); +#if __cplusplus <= 201402L volatile auto b2 = std::bind(X()); VERIFY( b2() == 2 ); const volatile auto b3 = std::bind(X()); VERIFY( b3() == 3 ); +#endif } void test02() @@ -63,11 +65,13 @@ void test02() const auto b1 = std::bind(X()); VERIFY( b1() == 1 ); +#if __cplusplus <= 201402L volatile auto b2 = std::bind(X()); VERIFY( b2() == 2 ); const volatile auto b3 = std::bind(X()); VERIFY( b3() == 3 ); +#endif } void test03() @@ -78,11 +82,13 @@ void test03() const auto b1 = std::bind(X(), _1, 0, _2); VERIFY( b1(0, 0) == 1 ); +#if __cplusplus <= 201402L volatile auto b2 = std::bind(X(), _1, _2, 0); VERIFY( b2(0, 0) == 2 ); const volatile auto b3 = std::bind(X(), _1, 0, _2); VERIFY( b3(0, 0) == 3 ); +#endif } void test04() @@ -93,11 +99,13 @@ void test04() const auto b1 = std::bind(X(), _1, 0, _2); VERIFY( b1(0, 0) == 1 ); +#if __cplusplus <= 201402L volatile auto b2 = std::bind(X(), _1, _2, 0); VERIFY( b2(0, 0) == 2 ); const volatile auto b3 = std::bind(X(), _1, 0, _2); VERIFY( b3(0, 0) == 3 ); +#endif } diff --git a/libstdc++-v3/testsuite/20_util/bind/cv_quals_2.cc b/libstdc++-v3/testsuite/20_util/bind/cv_quals_2.cc index 9252285bb2a..cd9b2042f55 100644 --- a/libstdc++-v3/testsuite/20_util/bind/cv_quals_2.cc +++ b/libstdc++-v3/testsuite/20_util/bind/cv_quals_2.cc @@ -33,11 +33,13 @@ void test01() const auto b0 = std::bind(X()); VERIFY( b0() == 0 ); +#if __cplusplus <= 201402L volatile auto b1 = std::bind(X()); VERIFY( b1() == 1 ); const volatile auto b2 = std::bind(X()); VERIFY( b2() == 2 ); +#endif } int main() -- 2.30.2