From 0148a838d09499a457ee2dbd07e5573711e7f32e Mon Sep 17 00:00:00 2001 From: Howard Hinnant Date: Thu, 19 May 2011 19:41:47 +0000 Subject: [PATCH] Simplied bind using __invoke. In the process, found and fixed a couple of bugs. C++11 only. git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@131667 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/functional | 44 ++++++++----------- .../func.bind.bind/invoke_lvalue.pass.cpp | 1 + .../func.bind.bind/invoke_rvalue.pass.cpp | 18 ++++++++ 3 files changed, 37 insertions(+), 26 deletions(-) diff --git a/include/functional b/include/functional index d009d639..aa2b4924 100644 --- a/include/functional +++ b/include/functional @@ -1510,21 +1510,12 @@ __mu(reference_wrapper<_Tp> __t, _Uj&) return __t.get(); } -template -struct __mu_return1 {}; - -template -struct __mu_return1 -{ - typedef typename result_of<_Ti(_Uj...)>::type type; -}; - template inline _LIBCPP_INLINE_VISIBILITY -typename __mu_return1::type -__mu_expand(_Ti& __ti, tuple<_Uj...>&& __uj, __tuple_indices<_Indx...>) +typename __invoke_of<_Ti&, _Uj...>::type +__mu_expand(_Ti& __ti, tuple<_Uj...>& __uj, __tuple_indices<_Indx...>) { - return __ti(_STD::forward::type>(get<_Indx>(__uj))...); + return __ti(_STD::forward<_Uj>(get<_Indx>(__uj))...); } template @@ -1532,7 +1523,7 @@ inline _LIBCPP_INLINE_VISIBILITY typename enable_if < is_bind_expression<_Ti>::value, - typename __mu_return1::value, _Ti, _Uj...>::type + typename __invoke_of<_Ti&, _Uj...>::type >::type __mu(_Ti& __ti, tuple<_Uj...>& __uj) { @@ -1582,7 +1573,7 @@ struct ____mu_return; template struct ____mu_return<_Ti, true, false, tuple<_Uj...> > { - typedef typename result_of<_Ti(_Uj...)>::type type; + typedef typename __invoke_of<_Ti&, _Uj...>::type type; }; template @@ -1619,7 +1610,7 @@ struct __bind_return; template struct __bind_return<_F, tuple<_BoundArgs...>, _TupleUj> { - typedef typename __invoke_return + typedef typename __invoke_of < _F&, typename __mu_return @@ -1633,7 +1624,7 @@ struct __bind_return<_F, tuple<_BoundArgs...>, _TupleUj> template struct __bind_return<_F, const tuple<_BoundArgs...>, _TupleUj> { - typedef typename __invoke_return + typedef typename __invoke_of < _F&, typename __mu_return @@ -1655,10 +1646,12 @@ __apply_functor(_F& __f, _BoundArgs& __bound_args, __tuple_indices<_Indx...>, template class __bind - : public __weak_result_type<_F> + : public __weak_result_type::type> { - _F __f_; - tuple<_BoundArgs...> __bound_args_; + typedef typename decay<_F>::type _Fd; + typedef tuple::type...> _Td; + _Fd __f_; + _Td __bound_args_; typedef typename __make_tuple_indices::type __indices; public: @@ -1675,17 +1668,16 @@ public: template _LIBCPP_INLINE_VISIBILITY - typename __bind_return<_F, tuple<_BoundArgs...>, tuple<_Args&&...> >::type + typename __bind_return<_Fd, _Td, tuple<_Args&&...> >::type operator()(_Args&& ...__args) { - // compiler bug workaround return __apply_functor(__f_, __bound_args_, __indices(), tuple<_Args&&...>(_STD::forward<_Args>(__args)...)); } template _LIBCPP_INLINE_VISIBILITY - typename __bind_return<_F, tuple<_BoundArgs...>, tuple<_Args&&...> >::type + typename __bind_return<_Fd, _Td, tuple<_Args&&...> >::type operator()(_Args&& ...__args) const { return __apply_functor(__f_, __bound_args_, __indices(), @@ -1736,19 +1728,19 @@ struct __is_bind_expression<__bind_r<_R, _F, _BoundArgs...> > : public true_type template inline _LIBCPP_INLINE_VISIBILITY -__bind::type, typename decay<_BoundArgs>::type...> +__bind<_F, _BoundArgs...> bind(_F&& __f, _BoundArgs&&... __bound_args) { - typedef __bind::type, typename decay<_BoundArgs>::type...> type; + typedef __bind<_F, _BoundArgs...> type; return type(_STD::forward<_F>(__f), _STD::forward<_BoundArgs>(__bound_args)...); } template inline _LIBCPP_INLINE_VISIBILITY -__bind_r<_R, typename decay<_F>::type, typename decay<_BoundArgs>::type...> +__bind_r<_R, _F, _BoundArgs...> bind(_F&& __f, _BoundArgs&&... __bound_args) { - typedef __bind_r<_R, typename decay<_F>::type, typename decay<_BoundArgs>::type...> type; + typedef __bind_r<_R, _F, _BoundArgs...> type; return type(_STD::forward<_F>(__f), _STD::forward<_BoundArgs>(__bound_args)...); } diff --git a/test/utilities/function.objects/bind/func.bind/func.bind.bind/invoke_lvalue.pass.cpp b/test/utilities/function.objects/bind/func.bind/func.bind.bind/invoke_lvalue.pass.cpp index 7417db32..6b18fa29 100644 --- a/test/utilities/function.objects/bind/func.bind/func.bind.bind/invoke_lvalue.pass.cpp +++ b/test/utilities/function.objects/bind/func.bind/func.bind.bind/invoke_lvalue.pass.cpp @@ -264,4 +264,5 @@ int main() { test_void_1(); test_int_1(); + test_void_2(); } diff --git a/test/utilities/function.objects/bind/func.bind/func.bind.bind/invoke_rvalue.pass.cpp b/test/utilities/function.objects/bind/func.bind/func.bind.bind/invoke_rvalue.pass.cpp index 9bde151c..4913a510 100644 --- a/test/utilities/function.objects/bind/func.bind/func.bind.bind/invoke_rvalue.pass.cpp +++ b/test/utilities/function.objects/bind/func.bind/func.bind.bind/invoke_rvalue.pass.cpp @@ -241,8 +241,26 @@ test_void_2() } } +int f_nested(int i) +{ + return i+1; +} + +int g_nested(int i) +{ + return i*10; +} + +void test_nested() +{ + using namespace std::placeholders; + assert(std::bind(f_nested, std::bind(g_nested, _1))(3) == 31); +} + int main() { test_void_1(); test_int_1(); + test_void_2(); + test_nested(); }