【问题标题】:Building a templated ODE solver构建模板化 ODE 求解器
【发布时间】:2014-04-26 08:46:10
【问题描述】:

我正在尝试使用以下函数声明实现模板化 ODE 求解器:

template<class ODEFunction,class StopCondition=decltype(continue_always<ODEFunction>)> 
bool euler_fwd(ODEFunction& f,typename State<ODEFunction>::type& x_0
    ,double t_0,double dt,size_t N_iter
    ,StopCondition& cond=continue_always<ODEFunction>);

完整来源:

/*From SO answer*/

template<class F>
struct State;

template <class R, class... A> 
struct State<R (*)(A...)>
    {
    typedef R type;
    };

/*End from SO answer*/


/**Default stop condition. Always return 0 to continue operation.
*/
template<class ODEFunction>
bool continue_always(const typename State<ODEFunction>::type& x_0,double t_0)
    {return 0;}

/**Euler forward solver
*/
template<class ODEFunction,class StopCondition=decltype(continue_always<ODEFunction>)> 
bool euler_fwd(ODEFunction& f,typename State<ODEFunction>::type& x_0
    ,double t_0,double dt,size_t N_iter
    ,StopCondition& cond=continue_always<ODEFunction>)
    {
    size_t k=0;
    while(N_iter)
        {
        if(cond(x_0,t_0))
           {return 1;}
        x_0+=dt*f(x_0,k*dt);
        --N_iter;
        ++k;
        }
    return 0;
    }

尝试用一个简单的函数调用 euler_fwd

double f(double x,double t)
    {return x;}

省略 continue_always 谓词,GCC 写道

错误:不完整类型“结构状态”的无效使用 bool continue_always(const typename State::type& x_0,double t_0)

...

test.cpp:18:47: error: no matching function for call to 'euler_fwd(double (&)(double, double), double&, double&, double&, size_t&)'

编辑:

如果我尝试跳过对 cond 使用默认参数:

euler_fwd(testfunc,x_0,t_0,dt,N,continue_always<decltype(testfunc)>);

我仍然收到错误

test.cpp:18:97: 注意:无法从重载函数 'continue_always' 解析地址

【问题讨论】:

  • 解决这个问题的一种可能方法是写template &lt;class R, class... A&gt; struct State&lt;R(A...)&gt;而不是template &lt;class R, class... A&gt; struct State&lt;R (*)(A...)&gt;
  • @Constructor 如果 ODEFunction 是一个函数对象而不是函数指针,是否可以定义非特化的 State 结构体,这样函数对象就不需要为其返回类型包含 typedef函数运算符?
  • 这里的典型解决方案是使用decltype:decltype(f(/* ... */))。但在这种情况下,这是不可能的(至少如此简单),因为据我所知,decltype(f(a, b)) == decltype(a)

标签: c++ templates metaprogramming


【解决方案1】:

与其尝试操纵函数类型(fcond 的类型),不如将状态设为模板参数?

#include <cstdlib> // for size_t
#include <functional>

template<class R>
bool continue_always(const R& x_0,double t_0)
{return 0;}

template<class R> 
bool euler_fwd(std::function<R(const R &)> f,R& x_0
  ,double t_0,double dt,size_t N_iter
  ,std::function<bool(const R&, double)> cond=continue_always<R>)
{
  size_t k=0;
  while(N_iter)
  {
    if(cond(x_0,t_0))
      {return 1;}
    x_0+=dt*f(x_0,k*dt);
    --N_iter;
    ++k;
  }
  return 0;
}

【讨论】:

  • R(const R&)是什么类型。以前从未见过这种语法
  • std::function&lt;R(const R&amp;)&gt; 是可调用对象的类型,它接受 const R&amp; 并返回 R。查看std::function 的文档。
  • 我提到了为该模板提供的类型参数。
  • 它是函数的类型类型(相对于函数指针)。例如,看到这个答案:stackoverflow.com/questions/7027922/…
猜你喜欢
  • 2014-02-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-27
  • 1970-01-01
  • 2020-05-09
  • 1970-01-01
相关资源
最近更新 更多