Without spending a long time reviewing the boost source code, could someone give me a quick rundown of how boost bind is implemented?
boost::bind is a generalization of the standard functions std::bind1st and std::bind2nd. It supports arbitrary function objects, functions, function pointers, and member function pointers, and is able to bind any argument to a specific value or route input arguments into arbitrary positions.
boost::function makes it possible to define a pointer to a function with a specific signature. Example 40.1 defines a pointer f that can point to functions that expect a parameter of type const char* and return a value of type int . Once defined, functions with matching signatures can be assigned to the pointer.
These placeholders tell boost::bind() to return a function object that expects as many parameters as the placeholder with the greatest number. If, as in Example 41.3, only the placeholder _1 is used, boost::bind() returns an unary function object – a function object that expects a sole parameter.
I like this piece of the bind
source:
template<class R, class F, class L> class bind_t { public: typedef bind_t this_type; bind_t(F f, L const & l): f_(f), l_(l) {} #define BOOST_BIND_RETURN return #include <boost/bind/bind_template.hpp> #undef BOOST_BIND_RETURN };
Tells you almost all you need to know, really.
The bind_template
header expands to a list of inline operator()
definitions. For example, the simplest:
result_type operator()() { list0 a; BOOST_BIND_RETURN l_(type<result_type>(), f_, a, 0); }
We can see the BOOST_BIND_RETURN
macro expands to return
at this point so the line is more like return l_(type...)
.
The one parameter version is here:
template<class A1> result_type operator()(A1 & a1) { list1<A1 &> a(a1); BOOST_BIND_RETURN l_(type<result_type>(), f_, a, 0); }
It's pretty similar.
The listN
classes are wrappers for the parameter lists. There is a lot of deep magic going on here that I don't really understand too much though. They have also overloaded operator()
that calls the mysterious unwrap
function. Ignoring some compiler specific overloads, it doesn't do a lot:
// unwrap template<class F> inline F & unwrap(F * f, long) { return *f; } template<class F> inline F & unwrap(reference_wrapper<F> * f, int) { return f->get(); } template<class F> inline F & unwrap(reference_wrapper<F> const * f, int) { return f->get(); }
The naming convention seems to be: F
is the type of the function parameter to bind
. R
is the return type. L
tends to be a list of parameter types. There are also a lot of complications because there are no less than nine overloads for different numbers of parameters. Best not to dwell on that too much.
By the way, if bind_t
is collapsed and simplified by including boost/bind/bind_template.hpp
, it becomes easier to understand like the following :
template<class R, class F, class L> class bind_t { public: typedef bind_t this_type; bind_t(F f, L const & l): f_(f), l_(l) {} typedef typename result_traits<R, F>::type result_type; ... template<class A1> result_type operator()(A1 & a1) { list1<A1 &> a(a1); return l_(type<result_type>(), f_, a, 0); } private: F f_; L l_; };
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With