cpp的功能方法

时间:2018-01-22 11:46:49

标签: c++ c++11

我正在尝试构建一些嵌套函数,如下所示(简化示例):

// the actual functions come from particle physics and are extremely ugly 
double f(double x){
  return 2*x+1;
}
//in reality a numerical derivative term
double F(const std::function<double(double)>& f, double x){
  return f(x) - f(x+1);
}
// in reality another higher order numerical derivative
double G(const std::function<double(double)>& f, double x){
  return f(x) + f(x+1);
}
// in reality a function where the index is supposed to control the degree of derivatives of the function
double H(const std::function<double(double)>& f, double x, int switch){
  if(0 == switch){ 
    return G(f(x)); 
  } else {
    return F(f(x));
  }
}

这是目标(2d用于演示):

double sum=0;
for(int i=0; i<1;++i){
  for(int j=0; j<1;++j){
    sum += H(H(f,i),j); 
  }
}

所以有两件事:

  1. 我想使用函数HFG之间切换(我的实际问题有3个案例)。
  2. 我想找到一种方法/概念来调用问题H(H(...)...)问题是函数f的类型,它是H的第一个参数,当我通过它时第二次类型不再是double(double)而是double(std::function<double(double)>,double(double),double)左右......
  3. 或其他方面: https://i.stack.imgur.com/XkbmJ.gif(无法发布图片,代表不够)

2 个答案:

答案 0 :(得分:2)

首先,不要明确使用std::function,而是让你的函数参数模板化,比如

template <typename Arg>
double F(Arg const & f, double x){
  return f(x) - f(x+1);
}

这为优化和通用性提供了更多空间。

其次,将所有函数转换为返回lambda:

template <typename Arg>
auto F(Arg const & f){
  return [f](double x){ return f(x) - f(x+1); };
}

template <typename Arg>
auto G(Arg const & f){
  return [f](double x){ return f(x) + f(x+1); };
}

template <typename Arg>
std::function<double(double)> H(Arg const & f, int which){
  if(0 == which){ 
    return F(f);
  } else {
    return G(f);
  }
}

注意auto返回类型:返回lambda需要这个。

现在你不打电话给F(f,x),而是Ff转换为它的衍生物(或其他东西),现在可以将其应用于x。这些现在可以像

一样使用
F(f)(0.1); // apply F(f) to x=0.1

F(F(G(f)))(0.5); // apply F(F(G(f))) to x=0.5

H(H(f,0),1)(4.2); // apply H(H(f,0),1) to x=4.2

答案 1 :(得分:1)

如果您有内部fswitch的值(NB更改该名称,switch是流量控制构造),那么您可以部分应用H然后将其传递给H

std::function<double(double)> partial_H(std::function<double(double)> f, int choice)
{
    return [f, choice](double x) { return H(f, x, choice); };
}