I am trying to understand the following example, that is similar (but not equal) to the one posted earlier on the SO Help understanding boost::bind placeholder arguments :
#include <boost/bind.hpp>
#include <functional>
struct X {
int value;
};
int main() {
X a = { 1 };
X b = { 2 };
boost::bind(std::less<int>(),
boost::bind(&X::value, _1),
boost::bind(&X::value, _2))
(a, b);
}
How is this possible, that the outer-most bind function knows that it has to pass the first argument to the second bind (that expects _1
), and the second argument to the third bind (that expects _2
)? The way I see this is that the inner binders are evaluated first, so they become two unary functional objects, that are later passed to the binder of less<int>
object. And when the newly created functional object is invoked with two objects, a
goes to the first inner-bind, and b
goes to the second. If I were right, we would use _1
twice. I must be wrong. I will repeat my question once again to make my problem clear: how the outer binder knows which placeholder was used in which inner binder?
Placeholders denote the arguments that are to be supplied to the resulting function object, and Boost. Bind supports up to nine such arguments. The placeholders are called _1, _2, _3, _4, and so on up to _9, and you use them in the places where you would ordinarily add the argument.
_1 is a placeholder. Boost. Bind defines placeholders from _1 to _9 . These placeholders tell boost::bind() to return a function object that expects as many parameters as the placeholder with the greatest number.
Purpose. 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.
Placeholders are namespaces which detect the position of a value in a function. Placeholders are represented by _1, _2, _3 etc.
arguments are packed in tuple (a,b) and passed to functors. then inner functor decides which tuple element it needs, e.g. try:
boost::bind(&X::value, _1)(a,b)
boost::bind(&X::value, _2)(a,b)
More generally, every value, regardless if it is constant/reference/placeholder is represented as functor which takes argument tuple and returns value.
bind(f, 10)(a) // still functor which discards arguments
Now, I am not a hundred percent sure this is how bind does it. however, this is how phoenix implement its functionality. if you are trying to understand mechanism of bind/lambda implementation, look at phoenix, it is very extensible and has excellent documentation.
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