C++11 接受带有任意输入的std::函数作为输入,不带模板

C++11 接受带有任意输入的std::函数作为输入,不带模板,c++11,math,input,lambda,std-function,C++11,Math,Input,Lambda,Std Function,出于学习目的: 我正在创建一个小的数值方法库,我正在尝试实现梯度目前我已经做了二维梯度和三维梯度。但我想把它推广到更高的维度 目前我有: matrix<double> analysis::gradient_2D(std::function<double(double, double)> fn, double x, double y) { matrix<double> R(2, 1); std::function<double(doubl

出于学习目的:

我正在创建一个小的数值方法库,我正在尝试实现梯度目前我已经做了二维梯度和三维梯度。但我想把它推广到更高的维度

目前我有:

matrix<double> analysis::gradient_2D(std::function<double(double, double)> fn, double x, double y)
{
    matrix<double> R(2, 1);

    std::function<double(double)> fnX = [fn, y](double xVar){ return fn(xVar, y); };
    std::function<double(double)> fnY = [fn, x](double yVar){ return fn(x, yVar); };

    R(1, 1) = differentiateBest(fnX, x);
    R(1, 2) = differentiateBest(fnY, y);

    return R;
}

matrix<double> analysis::gradient_3D(std::function<double(double, double, double)> fn, double x, double y, double z)
{
    matrix<double> R(3, 1);

    std::function<double(double)> fnX = [fn, y, z](double xVar){ return fn(xVar, y,z); };
    std::function<double(double)> fnY = [fn, x, z](double yVar){ return fn(x ,yVar, z); };
    std::function<double(double)> fnZ = [fn, x, y](double zVar){ return fn(x, y, zVar); };

    R(1, 1) = differentiateBest(fnX, x);
    R(1, 2) = differentiateBest(fnY, y);
    R(1, 3) = differentiateBest(fnZ, z);

    return R;
}

// Where 

double analysis::differentiateBest(std::function<double(double)> fn, double x)
{
    return derivative_1_Richardson_6O(fn,  x);
}
// For brevity , derivative_1_Richardson_6O also has the same input as differentiateBest
matrix analysis::gradient_2D(标准::函数fn,双x,双y)
{
矩阵R(2,1);
函数fnX=[fn,y](双xVar){返回fn(xVar,y);};
函数fnY=[fn,x](双yVar){返回fn(x,yVar);};
R(1,1)=微分基(fnX,x);
R(1,2)=微分基(fnY,y);
返回R;
}
矩阵分析::梯度3D(标准::函数fn,双x,双y,双z)
{
矩阵R(3,1);
函数fnX=[fn,y,z](双xVar){返回fn(xVar,y,z);};
函数fnY=[fn,x,z](双yVar){返回fn(x,yVar,z);};
函数fnZ=[fn,x,y](双zVar){返回fn(x,y,zVar);};
R(1,1)=微分基(fnX,x);
R(1,2)=微分基(fnY,y);
R(1,3)=微分基(fnZ,z);
返回R;
}
//在哪里
双重分析::DifferentiveBest(标准::函数fn,双x)
{
收益导数(fn,x);
}
//为简洁起见,导数_1_Richardson_6O也具有与微分贝斯特相同的输入
我知道它很冗长,但我喜欢它

问题: 我想做的是创建一个

// What do I do at the ...  ? 
matrix<double> analysis::gradient_ND(std::function<double(...)> fn, matrix<double>)
//在……我该怎么办?
矩阵分析::梯度(标准::函数fn,矩阵)
这样我就可以传递一个带有任意输入的std::函数,比如说N,我将传递 具有N个值的向量

我该怎么做呢?如果答案太长,链接也会很感激。 多谢各位

PS:我看到一个使用模板的方法,但是如果我在实现中使用模板,我将不得不将.cpp文件更改为其他文件,对吗?我想避免。如果使用模板是唯一的方法,那么我将不得不妥协。谢谢

template<class T>
struct array_view {
  T* b = nullptr; T* e = nullptr;
  T* begin() const { return b; }
  T* end() const { return e; }

  size_t size() const { return end()-begin(); }
  bool empty() const { return begin()==end(); }
  T& front()const{return *begin(); }
  T& back()const{return *std::prev(end()); }

  T& operator[](size_t i)const{return begin()[i]; }

  array_view( T* s, T* f ):b(s),e(f) {};
  array_view() = default;

  array_view( T* s, size_t l ):array_view(s, s+l) {}

  using non_const_T = std::remove_const_t<T>;
  array_view( std::initializer_list<non_const_T> il ):
    array_view(il.begin(), il.end()) {}
  template<size_t N>
  array_view( T(&arr)[N] ):array_view(arr, N){}
  template<size_t N>
  array_view( std::array<T,N>&arr ):array_view(arr.data(), N){}
  template<size_t N>
  array_view( std::array<non_const_T,N> const&arr ):
    array_view(arr.data(), N){}
  template<class A>
  array_view( std::vector<T,A>& v):
    array_view(v.data(), v.size()){}
  template<class A>
  array_view( std::vector<non_const_T,A> const& v):
    array_view(v.data(), v.size()){}
};
这是合理的

使用
array\u view
不会导致
.h
.cpp
代码拆分出现问题。唯一涉及的模板要么是固定的(数组视图本身),要么在构建数组视图时解析

matrix<double> R(pt.size(), 1);

auto make_tmp = [pt]{
  std::vector<double> tmp;
  tmp.reserve(pt.size());
  for (double x:pt)
    tmp.push_back(x);
  return tmp;
};

std::vector<std::function<double(double)>> partials;
partials.reserve(pt.size());
for (size_t i = 0; i < pt.size(); ++i) {
  partials.push_back(
    [&,i](double x){ auto tmp=make_tmp(); tmp[i]=x; return fn(tmp); };
  );
}
for (size_t i = 0; i < pt.size(); ++i) {
  R(1, i) = differentiateBest(partials[i], pt[i]);
}

return R;

是C++14版本。C++11版本将创建一个
tmp
变量并按值捕获它。

否,模板与包含翻译单位的文件名无关。诚然,模板可能相当复杂,您应该使用头文件对代码进行一定程度的组织;但这与模板本身无关,而是与代码复杂性有关。很抱歉延迟接受答案。@nnr上面的数组视图可能包含打字错误:我在其他地方发布了调试过的版本。搜索
site:stackoverflow,com-yakk-array\u-view
如果您需要帮助修复它。基本上,如果你想获取任意数量的参数,就要获取一系列迭代器:上面的内容只是对任意连续范围的迭代器进行抽象。如果我有更多问题,我会回来。谢谢你的回答。
matrix<double> R(pt.size(), 1);

auto make_tmp = [pt]{
  std::vector<double> tmp;
  tmp.reserve(pt.size());
  for (double x:pt)
    tmp.push_back(x);
  return tmp;
};

std::vector<std::function<double(double)>> partials;
partials.reserve(pt.size());
for (size_t i = 0; i < pt.size(); ++i) {
  partials.push_back(
    [&,i](double x){ auto tmp=make_tmp(); tmp[i]=x; return fn(tmp); };
  );
}
for (size_t i = 0; i < pt.size(); ++i) {
  R(1, i) = differentiateBest(partials[i], pt[i]);
}

return R;
  [&,i,tmp=make_tmp()](double x){ std::swap(tmp[i],x); double r=fn(tmp); std::swap(tmp[i],x); return r; };