【问题标题】:Add member functions and member variables based on template argument根据模板参数添加成员函数和成员变量
【发布时间】:2023-03-23 05:18:01
【问题描述】:

我有一系列函数{f_n} 其中f_0 是连续的,f_1 是连续可微的,$f_{n} \in C^{n}[a,b]$ 等等。我有一个 C++ 类,它通过向量 v 上的查找表对 f_n 进行数值评估

template<int n, typename Real=double>
class f
{
public:
    f() { /* initialize v */ }

    Real operator()(Real x) { /* find appropriate index for x, and interpolate */}

private:
    std::vector<Real> v;
};

但是,如果f 是可微分的(n &gt;= 1),我想添加一个成员函数:

template<int n, typename Real=double>
class f
{
public:
    f() { /* initialize v and dv */ }

    Real operator()(Real x) { /* find appropriate index for x, and interpolate on v */}

    Real prime(Real x) { /* find appropriate index for x, and interpolate on dv */}

private:
    std::vector<Real> v;
    std::vector<Real> dv;
};

我还想为 n >= 2 添加一个二阶导数成员,依此类推。 这可以在一个班级中完成吗? (我可以接受 C++17 语法。)

【问题讨论】:

  • 如何检查n 是否大于或等于1?这应该是非类型模板参数吗?
  • @GuillaumeRacicot:我的错,错字。应该是int n
  • “这可以在一个班级中完成吗?” 嗯,不。每对模板参数都有一个不同的类。所以本质上不止一个类。您是指单个(模板)声明吗?

标签: c++ templates c++17 sfinae template-specialization


【解决方案1】:

对于每个n &gt; 0,我们添加一个新成员函数,将该值作为从下一层继承的参数:

template<int n, typename Real=double>
class f
    : public f<n-1, Real>
{
public:
    f() { /* initialize dv */ }

    using f<n-1, Real>::prime;
    Real prime(Real x, integral_constant<int, n>) { 
        /* find appropriate index for x, and interpolate on dv */
    }

protected:
    std::vector<Real> dv;
};

基础版本添加operator():

template<typename Real=double>
class f<0, Real>
{
public:
    f() { /* initialize v */ }

    Real operator()(Real x) { /* find appropriate index for x, and interpolate */}
    Real prime(Real x) { return (*this)(x); }

protected:
    std::vector<Real> v;
};

这意味着一阶导数调用prime(x, integral_constant&lt;int, 1&gt;{}),二阶导数调用prime(x, integral_constant&lt;int, 2&gt;{})

【讨论】:

    【解决方案2】:

    您可以简单地拥有一个模板成员函数和一个 static_assert 来确保您不会使用您的类不支持的派生类。例如:

    template <int n, /* other stuff */>
    class f
    {
      /* Other stuff not shown */
      template <int p>
      Real prime(Real x)
      {
        static_assert(p <= n, "unsupported derivative");
        /* do whatever you need to to implement the pth derivative */
      }
    };
    

    因此,f 类型的对象将支持 prime() 但不支持 prime() 等。如果您不小心在 f 类型的对象上调用 prime,编译器会打电话给你的。是否要将 prime&lt;0&gt; 视为与 operator () 相同,或者更改您的 static_assert 以包含对 p &gt; 0 的检查,由您决定。

    【讨论】:

      猜你喜欢
      • 2015-05-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-03-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多