我有一系列函数{f_n}
,其中f_0
是连续的,f_1
是连续可微的,$ f_ {n} \在C ^ {n} [a,b] $等等。我有一个C ++类,通过矢量f_n
上的查找表给出v
的数值评估
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 >= 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 > 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<int, 1>{})
,二阶导数称为prime(x, integral_constant<int, 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 <1>的对象将支持prime <1>()但不支持prime <2>()等。如果您不小心在f <1>类型的对象上调用prime <3>,编译器将调用您在它上面。由您决定是否要将prime<0>
视为与operator ()
相同或更改static_assert以包含对p > 0
的检查。