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
This commit is contained in:
Howard Hinnant 2011-05-19 19:41:47 +00:00
parent 57cff290a4
commit 0148a838d0
3 changed files with 37 additions and 26 deletions

View File

@ -1510,21 +1510,12 @@ __mu(reference_wrapper<_Tp> __t, _Uj&)
return __t.get(); return __t.get();
} }
template <bool _IsBindExpr, class _Ti, class ..._Uj>
struct __mu_return1 {};
template <class _Ti, class ..._Uj>
struct __mu_return1<true, _Ti, _Uj...>
{
typedef typename result_of<_Ti(_Uj...)>::type type;
};
template <class _Ti, class ..._Uj, size_t ..._Indx> template <class _Ti, class ..._Uj, size_t ..._Indx>
inline _LIBCPP_INLINE_VISIBILITY inline _LIBCPP_INLINE_VISIBILITY
typename __mu_return1<true, _Ti, _Uj...>::type typename __invoke_of<_Ti&, _Uj...>::type
__mu_expand(_Ti& __ti, tuple<_Uj...>&& __uj, __tuple_indices<_Indx...>) __mu_expand(_Ti& __ti, tuple<_Uj...>& __uj, __tuple_indices<_Indx...>)
{ {
return __ti(_STD::forward<typename tuple_element<_Indx, _Uj>::type>(get<_Indx>(__uj))...); return __ti(_STD::forward<_Uj>(get<_Indx>(__uj))...);
} }
template <class _Ti, class ..._Uj> template <class _Ti, class ..._Uj>
@ -1532,7 +1523,7 @@ inline _LIBCPP_INLINE_VISIBILITY
typename enable_if typename enable_if
< <
is_bind_expression<_Ti>::value, is_bind_expression<_Ti>::value,
typename __mu_return1<is_bind_expression<_Ti>::value, _Ti, _Uj...>::type typename __invoke_of<_Ti&, _Uj...>::type
>::type >::type
__mu(_Ti& __ti, tuple<_Uj...>& __uj) __mu(_Ti& __ti, tuple<_Uj...>& __uj)
{ {
@ -1582,7 +1573,7 @@ struct ____mu_return;
template <class _Ti, class ..._Uj> template <class _Ti, class ..._Uj>
struct ____mu_return<_Ti, true, false, tuple<_Uj...> > 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 <class _Ti, class _TupleUj> template <class _Ti, class _TupleUj>
@ -1619,7 +1610,7 @@ struct __bind_return;
template <class _F, class ..._BoundArgs, class _TupleUj> template <class _F, class ..._BoundArgs, class _TupleUj>
struct __bind_return<_F, tuple<_BoundArgs...>, _TupleUj> struct __bind_return<_F, tuple<_BoundArgs...>, _TupleUj>
{ {
typedef typename __invoke_return typedef typename __invoke_of
< <
_F&, _F&,
typename __mu_return typename __mu_return
@ -1633,7 +1624,7 @@ struct __bind_return<_F, tuple<_BoundArgs...>, _TupleUj>
template <class _F, class ..._BoundArgs, class _TupleUj> template <class _F, class ..._BoundArgs, class _TupleUj>
struct __bind_return<_F, const tuple<_BoundArgs...>, _TupleUj> struct __bind_return<_F, const tuple<_BoundArgs...>, _TupleUj>
{ {
typedef typename __invoke_return typedef typename __invoke_of
< <
_F&, _F&,
typename __mu_return typename __mu_return
@ -1655,10 +1646,12 @@ __apply_functor(_F& __f, _BoundArgs& __bound_args, __tuple_indices<_Indx...>,
template<class _F, class ..._BoundArgs> template<class _F, class ..._BoundArgs>
class __bind class __bind
: public __weak_result_type<_F> : public __weak_result_type<typename decay<_F>::type>
{ {
_F __f_; typedef typename decay<_F>::type _Fd;
tuple<_BoundArgs...> __bound_args_; typedef tuple<typename decay<_BoundArgs>::type...> _Td;
_Fd __f_;
_Td __bound_args_;
typedef typename __make_tuple_indices<sizeof...(_BoundArgs)>::type __indices; typedef typename __make_tuple_indices<sizeof...(_BoundArgs)>::type __indices;
public: public:
@ -1675,17 +1668,16 @@ public:
template <class ..._Args> template <class ..._Args>
_LIBCPP_INLINE_VISIBILITY _LIBCPP_INLINE_VISIBILITY
typename __bind_return<_F, tuple<_BoundArgs...>, tuple<_Args&&...> >::type typename __bind_return<_Fd, _Td, tuple<_Args&&...> >::type
operator()(_Args&& ...__args) operator()(_Args&& ...__args)
{ {
// compiler bug workaround
return __apply_functor(__f_, __bound_args_, __indices(), return __apply_functor(__f_, __bound_args_, __indices(),
tuple<_Args&&...>(_STD::forward<_Args>(__args)...)); tuple<_Args&&...>(_STD::forward<_Args>(__args)...));
} }
template <class ..._Args> template <class ..._Args>
_LIBCPP_INLINE_VISIBILITY _LIBCPP_INLINE_VISIBILITY
typename __bind_return<_F, tuple<_BoundArgs...>, tuple<_Args&&...> >::type typename __bind_return<_Fd, _Td, tuple<_Args&&...> >::type
operator()(_Args&& ...__args) const operator()(_Args&& ...__args) const
{ {
return __apply_functor(__f_, __bound_args_, __indices(), return __apply_functor(__f_, __bound_args_, __indices(),
@ -1736,19 +1728,19 @@ struct __is_bind_expression<__bind_r<_R, _F, _BoundArgs...> > : public true_type
template<class _F, class ..._BoundArgs> template<class _F, class ..._BoundArgs>
inline _LIBCPP_INLINE_VISIBILITY inline _LIBCPP_INLINE_VISIBILITY
__bind<typename decay<_F>::type, typename decay<_BoundArgs>::type...> __bind<_F, _BoundArgs...>
bind(_F&& __f, _BoundArgs&&... __bound_args) bind(_F&& __f, _BoundArgs&&... __bound_args)
{ {
typedef __bind<typename decay<_F>::type, typename decay<_BoundArgs>::type...> type; typedef __bind<_F, _BoundArgs...> type;
return type(_STD::forward<_F>(__f), _STD::forward<_BoundArgs>(__bound_args)...); return type(_STD::forward<_F>(__f), _STD::forward<_BoundArgs>(__bound_args)...);
} }
template<class _R, class _F, class ..._BoundArgs> template<class _R, class _F, class ..._BoundArgs>
inline _LIBCPP_INLINE_VISIBILITY 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) 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)...); return type(_STD::forward<_F>(__f), _STD::forward<_BoundArgs>(__bound_args)...);
} }

View File

@ -264,4 +264,5 @@ int main()
{ {
test_void_1(); test_void_1();
test_int_1(); test_int_1();
test_void_2();
} }

View File

@ -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() int main()
{ {
test_void_1(); test_void_1();
test_int_1(); test_int_1();
test_void_2();
test_nested();
} }