views:

93

answers:

1

I am trying to understand the following example, that is similar (but not equal) to the one posted earlier on the SO http://stackoverflow.com/questions/2120725/help-understanding-boostbind-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?

+3  A: 

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.

aaa
ok, I get it. But what happens if one of the binded arguments is not a binder, e.g. costant value? I mean: boost::bind(std::less<int>(), boost::bind( How does it know to which argument it should assign generated tuple?
MarcAndreson
@Mar I have updated my answer, feel free to look
aaa