【发布时间】:2018-10-05 16:44:52
【问题描述】:
我想知道在 C++ 中组合数学运算符是否有一个优雅的解决方案。对于操作员,我的意思类似于以下内容:
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);
}
};
上面的类使用了一个“辅助函数”h(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...
return 0;
}
现在,我想组合运算符两次或更多次,即计算 A^2(f,2.0)。在上面的示例中,这将返回 h(x)*h(x)*f(x)。请注意,这是 not 函数组合,即我不想计算 A(A(f,2.0),2.0)。相反,考虑矩阵的计算能力:如果h(x) = M(矩阵),我想要M*M*...*M*x。
我能够使用std::bind() 来达到我想要的A^2 的结果(但不是更高的权力!)如下:
auto g = std::bind(&ApplyOp<Helper>::operator()<F>,&A,f,std::placeholders::_1);
使用生成的g,我可以通过简单地调用A(g,2.0) 来应用A^2(f,2.0)。对于上面的例子,这将返回h(x)*h(x)*f(x) = x*x*x*x*exp(x)
我如何将其概括为迭代应用运算符A N 次?我真的很喜欢here 发布的答案,但它在这里不太适用。我尝试过嵌套std:binds,但很快就陷入了深层编译器错误。
有什么想法吗?
完整的工作示例:
#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;
}
【问题讨论】:
-
要拥有
h(x)*h(x)*f(x),你必须改为拥有h1(x) = h(x)*h(x)并使用ApplyOp<Helper1> A(h1);。 -
使用模板和模板专业化
-
@Jarod42 这有点没抓住重点。我想要一个更通用的解决方案,它不依赖于运算符的特定形式。
-
@user9335240 我不确定我是否了解专业化有何帮助 - 你能再解释一下吗?
-
@Jarod42 您可以创建一个模板函数,其模板参数为 int,递归解析为相同的函数,但模板参数减一,并在此参数 == 时进行专门化2 做绑定
标签: c++ c++11 functional-programming