Reputation: 2295
Suppose you would like to perform mathematical operations on functions. Mathematically we know that f(x)*g(x)
is also a function if f
and g
are.
How would one go about expressing that with std::function
? I was thinking of overloading the mathematical operators something so:
typedef std::function<double(double)> func;
func operator * (const func &f, func &g)
{
auto temp = [&] () { return f( ?? ) * g ( ?? ); };
return temp;
}
But I'm not sure how the arguments of f
and g
would come into play here. Could I use std::placeholders
for this? What would be the correct way to proceed?
Upvotes: 0
Views: 86
Reputation: 180120
There's no need for type erasure in the return type. You'd really want something like this:
class composed {
std::function<double(double)> f;
std::function<double(double)> g;
public:
composed(std::function<double(double)> f, std::function<double(double)> g) : f(f), g(g) { }
double operator()(double x) { return f(x) * g(x); }
};
inline composed operator*(std::function<double(double)> f, std::function<double(double)> g) { return composed(f,g); }
This is more efficient than return a std::function<double(double)>
. composed
can still be convertedto one, if the caller wants to. But when you just pass it to std::transform
, calling composed
directly is more efficient.
In fact, an industrial-strength implementation of operator*
would try to capture the actual types of f
and g
as well, so composed
would become a template.
Upvotes: 1
Reputation: 137415
It would be
func operator* (const func &f, const func &g)
{
return [=](double x) { return f(x) * g(x); }
}
I don't recommend doing it, though. For one, because you can't add things to std
, this operator can't be found by ADL, so you have to rely on plain unqualified lookup, which is brittle at best. Also, multiple layers of std::function
is quite inefficient.
Upvotes: 2