The placeholders in the bound argument list are the special symbols _2 and _1. To make it possible to avoid name
collisions, these are in the special namespace std::placeholders. The using directive above allows us to refer
to them directly, instead of say std::placeholders::_1. The call arguments are listed in the second set of
parentheses, which is simply the normal syntax for an argument list in a function call,
The placeholder notation requires some care to understand. The placeholder indicates which function argument
should be filled with which value from the call argument list. The position of the placeholder in the bound argument
list corresponds to the same position in the function argument list, and the number of the placeholder corresponds to
a value in the call argument list.
Thus, in the above example, the placeholder _2 appears first in the bound argument list, which means it specifies
the first argument to be given to sum3. Its number, 2, specifies the second argument in the call argument list. Thus
the second call argument item will be the first function argument. Likewise, _1 in the third position means that this
argument to sum3 should be taken from the first of the supplied values in the call arguments. In this case, bind
creates a function object that can be called with two integer values, the first of which is given to sum3 as its third
argument, the second of which is given to sum3 as its first argument, and the second argument given to sum3 is the
bound value of int2, which is copied and stored when the function object is created.
Any mixture of placeholders and ordinary arguments can appear, as long as the number of items in the bound
argument list equals the number of function arguments. In contrast, the call argument list can include extra values -
they don't all have to be used, as long as the wrapped function gets all the arguments it needs. Likewise, it can
include fewer values if some of them get used more than once. To illustrate the extremes, we could write both of the
following:
bind(sum3, _2, int2, _5)(int3, int1, int4, int5, int6);
bind(sum3, _1, _1, _1)(int1);
The first call uses the second and fifth call arguments and ignores the others. The second call uses the same call
argument for all three function arguments.
Suppose the function takes a call-by-reference parameter. If the corresponding argument is a modifiable location
(an lvalue, like a non-const variable), the function can modify it. Since mod23 modifies its second and third
arguments, if we write:
cout << int1 << ' ' << int2 << ' ' << int3 << endl;
bind(mod23, int1, _1, _2)(int2, int3);
cout << int1 << ' ' << int2 << ' ' << int3 << endl;
Both int2 and int3 will have different values in the two output statements.
We can also use constants as the call arguments, as long as the function doesn't try to modify them:
result = bind(sum3, _1, _2, _3)(100, 200, 300);
bind(mod23, int1, _1, _2)(100, 200); // compile error!
We can also use rvalues such as expressions or function calls as the call arguments, as long as the function doesn't
try to modify them:
result = bind(sum3, _1, _2, _3)(foo(), int1+3, 300);
bind(mod23, _1, int2, _2)(foo(), int3);
bind(mod23, int1, _1, _2)(foo(), int1+3); // compile error!
Using bind in algorithms
All the background has now been presented for how to use bind in the context of an algorithm like for_each
running over a container of objects. When the algorithm is executed, the dereferenced iterator has a single value, and
this single value will constitute the single call argument to the bind function object.
3