7

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?

Community
  • 1
  • 1
Marc Andreson
  • 3,405
  • 5
  • 35
  • 51

1 Answers1

6

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.

Anycorn
  • 50,217
  • 42
  • 167
  • 261
  • 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(), boost::bind(&X::value, _1), 10)(a); How does it know to which argument it should assign generated tuple? – Marc Andreson Sep 20 '10 at 22:05