Boost logo

Boost Users :

Subject: Re: [Boost-users] [bind] Possible to use variadic templates with bind?
From: Peter Dimov (pdimov_at_[hidden])
Date: 2010-07-21 12:23:25


Steve Lorimer wrote:
> Hi
>
> Is it possible to pass variadic template arguments to bind, such that bind
> uses them as the placeholder arguments (_1, _2, _3 etc)
>
> I show my use case below.
...
> template<class T, typename... Args> struct cb { typedef void
> (T::*type)(Args...); };
...
> job_t(typename cb<T, Args...>::type cb, boost::shared_ptr<T> that,
> boost::shared_ptr<job_queue> q) :
> arg_func(boost::bind(cb, that, Args...)), queue(q) {} // normally
> would be _1, _2, _3, etc

An interesting puzzle. I tried to apply the 'Indexes' technique shown in the
bind implementation section of

http://osl.iu.edu/~dgregor/cpp/variadic-templates.pdf

and ended up with the following:

#include <boost/bind.hpp>
#include <boost/function.hpp>

template<int...> struct int_tuple {};

// make indexes impl is a helper for make indexes
template<int I, typename IntTuple, typename... Types>
struct make_indexes_impl;

template<int I, int... Indexes, typename T, typename... Types>
struct make_indexes_impl<I, int_tuple<Indexes...>, T, Types...>
{
    typedef typename make_indexes_impl<I+1,
        int_tuple<Indexes..., I>,
        Types...>::type type;
};

template<int I, int... Indexes>
struct make_indexes_impl<I, int_tuple<Indexes...> >
{
    typedef int_tuple<Indexes...> type;
};

template<typename... Types>
struct make_indexes: make_indexes_impl<0, int_tuple<>, Types...> { };

template< class T, class... Args, int... Indexes >
boost::function< void(Args...) > make_func_helper( void (T::* pm) (Args...),
T * that, int_tuple< Indexes... > )
{
    return boost::bind( pm, that, boost::arg<Indexes+1>()... );
}

template< class T, class... Args >
boost::function< void(Args...) > make_func( void (T::* pm) (Args...), T *
that )
{
    return make_func_helper( pm, that, typename
make_indexes<Args...>::type() );
}

struct X
{
    void f( int, int )
    {
    }
};

int main()
{
    X x;
    boost::function<void(int, int)> f = make_func( &X::f, &x );
    f( 1, 2 );
}

Hope this helps.
 


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net