Boost logo

Boost Users :

From: Dave Slutzkin (daveslutzkin_at_[hidden])
Date: 2005-07-28 18:53:51


On Fri, 29 Jul 2005 11:10:07 +1200, "Oleg Smolsky"
<oleg.smolsky_at_[hidden]> said:
> >> // This doesn't compile
> >> //std::for_each(v.begin(), v.end(),
> >> // boost::bind(&Handler::Test2, _1, _2, a, b));
> > This creates a functor with two arguments, _1 and _2, which calls
> > Handler::Test2 with _1 as this, _2 as argument 1 of Test2, a as
> > argument 2 of Test2 and b as argument 3 of Test2. But Test2 only
> > has two arguments, and for_each only takes a functor with one
> > argument.
> This is very confusing.... Let me paraphrase your explanation: I was
> trying to feed an extra argument to bind, which takes parameters in
> this fashion: boost::bind(function, this, arg1, arg2, arg3, etc)
>
> Right?

Not exactly. Bind takes a variable number of arguments, so don't worry
about that. Bind will create a functor which calls the function given
as the first argument, with the arguments given in the rest of the call.
 So it's like:

bind(function, value1, value2, value3, value4, ...)

Which will generate a functor something like this:

class anonymous_functor
{
public:
  void operator()()
  {
    function(value1, value2, value3, value4, ...);
  }
};

If function is a member function, then bind obviously needs an object
(of the correct type) for it to act on. The object (or 'this' pointer
to it) is then the first argument of the bind expression. So it will
look more like this:

bind(&class::function, object, value1, value2, value3, ...)

Generating:

class anonymous_functor_for_member
{
public:
  void operator()()
  {
    object.function(value1, value2, value3, ...)
  }
};

Note that neither of these functors take any arguments. This is because
no placeholders were used in their bind expressions.

> If yes, what's the exact meaning of _1, _2 placeholders? Also, how
> does that mash with functions vs methods?

If any of value1, value2, etc are a placeholder like _1, _2, etc, then
the generated functor will have an argument corresponding to that
placeholder. The simple case:

bind(function, _1)

Generates:

class anonymous_one_arg_functor
{
public:
  void operator()(some_type arg1)
  {
    function(arg1)
  }
};

The functor will have a number of arguments corresponding to the highest
placeholder used. So if you can see an _2 in your expression, the
functor will have two arguments; _even_ if you don't use _1. So:

bind(function, _2, value1, value2, ...)

Generates:

class anonymous_two_arg_functor
{
public:
  void operator()(some_type arg1, some_other_type arg2)
  {
    function(arg2, value1, value2, ...)
  }
};

Note that arg1 is passed to the functor but not used in the body,
because you didn't use _1 in your bind expression.

When you talk about member functions, it's all consistent with what I've
previously said. The second argument to bind is the object, which can
easily be a placeholder:

bind(&class::function, _1, _2, value1, value2, ...)

Generates:

class anonymous_two_arg_functor_for_member
{
public:
  void operator()(class arg1, some_type arg2)
  {
    arg1.function(arg2, value1, value2, ...)
  }
};

Does this make sense?

Dave.

-- 
  Dave Slutzkin
  Melbourne, Australia
  daveslutzkin_at_[hidden]

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