C++ has a rather restrictive version of currying, namely
the
function binders that come with the
C++ Standard
Library.
People find these unsatisfactory for various reasons, and clamor for
"real" function closures directly in the language.
However, this violates a basic C++ design goal: You don't pay for
what you don't use. Besides, they can be implemented
in C++; people put out entire libraries devoted to them.
So let's make a real closure in C++. There are two ways to do
it:
The following code is an example of the second method. It has a lot
of issues as to flexibility, thread-safety, and efficiency, but these can
be overcome with appropriate safeguards. That's what the existing
lambda libraries do, I hope.
For the sake of clarity, we will present our "naive" version:
template <class R, class P1, class P2>
class lambda2
{
public:
typedef R (*func_t)(P1, P2);
lambda2 (func_t ifunc, P2 ip2): func (ifunc), p2 (ip2)
{}
lambda2 (lambda2 const &ilambda): func (ilambda.func),
p2 (ilambda.p2) {}
lambda2 &operator= (lambda2<R, P1, P2> const &nlambda)
{
func = nlambda.func;
p2 = nlambda.p2;
return *this;
}
P2 bound() const { return p2; }
lambda2 &rebind (func_t nfunc) { func=nfunc; return
*this; }
lambda2 &rebind (P2 np2) { p2 = np2; return *this;
}
//
// Finally, the point to all of this.
//
R operator() (P1 p1) { return func (p1, p2); }
private:
func_t func;
P2 p2;
};
The template above may look formidable, but it is the implementation
of our closure. The implementation of
closures can't be any less complex than what appears above.
The difference between C++ and the languages where closures are "built
in" is that in those languages, you can't see the implementation.
This being C++, the implementation code would appear in a header you
#include in your source code.
All you need to provide is a function to lambda-ize.
Given the following function
double divide (double p1, double p2)
{
return p1 / p2;
}
You could do the following:
typedef lambda2<double,double,double> lambda2_d3;
//
// Down in your code:
//
lambda2_d3 lam (divide, 2);
cout << lam (8); // prints "4"
cout << lam (7); // prints "3.5"
(I wrote and tested this code with Borland C++ Builder 5. Borland has
a version of this compiler you can download for free.)