The function binders that come with the
C++ Standard
Library are that library's attempt at the construct known variously as
"
lambda", "
currying function", or "
closure". Being an example
of
generic programming, the function binders are, of course,
templates,
whose arguments must meet specific requirements before you can use them.
Each binder consists of a class definition which contains the bound operator,
and a function which does the binding.
Thus:
namespace std {
template <class Operation>
class binder1st: public unary_function<typename Operation::second_argument_type,
typename Operation::result_type>
{
protected:
Operation Op;
typename Operation::first_argument_type value;
public:
binder1st (const Operation &x,
const typename Operation::first_argument_type y): Op (x), value (y) {}
typename Operation::result_type operator()(const typename
Operation::second_argument_type &X) const
{
return Op (value, X);
}
};
template <class Operation, class T>
binder1st<Operation> bind1st (const Operaiton &Op, const
T &x)
{
return binder1st<Operation (Op, x);
}
} // namespace std
A Binder2nd class and a bind2nd() function
are defined analogously.
To use this beast, you need a functor class which meets the requirements:
A type declaration specifying the functor's first argument type,
A type declaration specifying the functor's second argument type,
A type declaration specifying the functor's result type, and
Finally, a declared Operator() that performs the actual operaiton.
Have I scared you away yet? Just wait!
Why would you use a function binder in the first place? Well,
perhaps you want to use an algorithm from the Standard Library that operates
on one argument, but the operation you wanted to use takes two arguments,
with one always the same. Let's say you had a std::vector<int>
and you wanted to count the ints less than 37. You can use
std::count_if
and std::bind2nd to do this for you:
//
// In some header somewhere
//
template <class N1, class N2>
struct Less
{
typedef N1 first_argument_type;
typedef N2 second_argument_type;
typedef bool result_type;
static bool operator()(N1 const &n1, N2 const &n2)
{
return n1<n2;
}
};
//
// Later, Down in your code, count the number of
// elements of a vector less than 37.
//
int lt37 (std::vector<int> const &vi)
{
return std::count_if (vi.begin(), vi.end(), std::bind2nd(Less<int,int>(),
37));
}
Ugly, huh? The ungainly syntax required to use the function binders
drives a lot of people away from using them (much like a lot of the rest
of the C++ Standard Library).
On top of all that, these definitions are rather limiting.

You can't use them with functions that have a void return
type.

You need to declare an Operation object even if it doesn't
have any state (the temporary object Less<int,int>() above
shouldn't be necessary).

You can only bind to functions that don't change their arguments!
This last problem is the one that leaves people fuming at the Standards
Committee.
So, if you had:
template <class OSTREAM, class T>
struct Inserter
{
typedef OSTREAM &first_argument_type;
typedef T second_argument_type;
typedef OSTREAM result_type;
static OSTREAM &operator()(OSTREAM &os, T const
&t)
{
return os::operator<<(t);
}
};
You couldn't use bind1st() to bind to a particular ostream
into an Inserter object for use in a standard algorithm.
std::ostream &dumpvec (std::ostream &os, std::vector<int>
const &v)
{
//
// Sorry, won't work!
// (can't take a reference to a reference)
//
return std::for_each (v.begin(),
v.end(),
std::bind1st (Inserter<std::ostream,
int >, os));
}
The problem arises from the overzealous use of const references for function arguments.
Bjarne Stroustrup himself has submitted a defect report for the last
problem, plus a possible solution^{1}, but the Committee has yet
to agree upon whether it's even a defect in the Standard or not.
In the meantime, there are two solutions.

Roll your own binder1st and binder2nd,
outside of namespace std. If you've read this far in the
writeup, I suppose you know what you have to do to fix the problem.

I have read in a few places that you are allowed to specialize templates
in the Standard Library for classes you define yourself. Thus, you
can make a specialization of std::binder1st<Operation>
for any Operation you define! Be warned: I'm not
completely sure if you can do this. The standard seems to be pretty
strict on putting things in namespace std.
Thus:
namespace my {
template <class Operation>
class binder1st: public unary_function<typename Operation::second_argument_type,
typename Operation::result_type>
{
protected:
Operation Op;
typedef typename Operation::first_argument_type bound_type;
bound_type value;
public:
typedef typename Operator::second_argument_type first_argument_type;
typedef typename Operator::result_type result_type;
binder1st (Operation x, bound_type y): Op (x), value
(y) {}
typename Operation::result_type operator()(typename Operation::second_argument_type
X)
{
return Op (value, X);
}
};
} // namespace my
Or, if allowed:
namespace std {
template <class T>
class binder1st<Inserter <std::ostream, T>/**/>: public
unary_function<T, ostream>
{
protected:
Inserter<std::ostream, T> &os;
typename Operation::first_argument_type value;
public:
binder1st (Operation const &x,
typename Operation::first_argument_type y): Op (x), value (y) {}
typename Operation::result_type operator()(const T &X)
{
return Op (value, X);
}
};
^{1}I disagree with the solution, but then again the Committee
never heard of me.