I'm wondering if there is an elegant solution for composing mathematical operators in C++. By operator, I mean something like the following:
template<class H>
class ApplyOp {
H h;
public:
ApplyOp(){}
ApplyOp(H h_i) : h(h_i) {}
template<class argtype>
double operator()(argtype f,double x){
return h(x)*f(x);
}
};
The above class makes use of a "helper function" h(x)
. For example,
struct Helper{
Helper(){}
double operator()(double x){return x*x;}
};
struct F{
F(){}
double operator()(double x){return exp(x);}
};
int main()
{
Helper h;
F f;
ApplyOp<Helper> A(h);
std::cout<<"A(f,2.0) = "<<A(f,2.0)<<std::endl; //Returns 2^2*exp(2) = 29.5562...
return 0;
}
Now, I would like to compose the operator twice or more times, i.e. compute A^2(f,2.0)
. In the above example, this would return h(x)*h(x)*f(x)
. Note that this is not function composition, i.e. I do not want to compute A(A(f,2.0),2.0)
. Rather, think in terms of computing powers of a matrix: if h(x) = M
(a matrix), I want M*M*...*M*x
.
I was able to use std::bind()
to achieve my desired result for A^2
(but not higher powers!) as follows:
auto g = std::bind(&ApplyOp<Helper>::operator()<F>,&A,f,std::placeholders::_1);
With the resulting g
, I can apply A^2(f,2.0)
by simply calling A(g,2.0)
. With the above examples, this would return h(x)*h(x)*f(x) = x*x*x*x*exp(x)
How would I generalize this to iteratively applying the operator A
N times? I really liked the answer posted here, but it doesn't quite work here. I tried doing nested std:bind
s but quickly got into deep compiler errors.
Any ideas?
Complete working example:
#include<iostream>
#include<math.h>
#include<functional> //For std::bind
template<class H>
class ApplyOp {
H h;
public:
ApplyOp(){}
ApplyOp(H h_i) : h(h_i) {}
template<class argtype>
double operator()(argtype f,double x){
return h(x)*f(x);
}
};
struct Helper{
Helper(){}
double operator()(double x){return x*x;}
};
struct F{
F(){}
double operator()(double x){return exp(x);}
};
int main()
{
Helper h;
F f;
ApplyOp<Helper> A(h);
std::cout<<"A(f,2.0) = "<<A(f,2.0)<<std::endl; //Returns 2^2*exp(2) = 29.5562...
auto g = std::bind(&ApplyOp<Helper>::operator()<F>,&A,f,std::placeholders::_1);
std::cout<<"A^2(f,2.0) = "<<A(g,2.0) <<std::endl; //Returns 2^4*exp(2) = 118.225...
return 0;
}