仅针对类的特定模板实例化声明成员函数

Declare member function only for specific template instantiation of class

本文关键字:实例化 声明 成员 函数      更新时间:2023-10-16

是否可以仅为类的特定模板实例化声明成员函数?这就是我想这样做的原因:

// Polynomial<N> is a polynomial of degree N
template<int N>
class Polynomial {
public:
    //... various shared methods e.g...
    double eval(double x) const;
    Polynomial<N-1> derivative() const;
    Polynomial<N+1> integralFrom(double x0) const;
    // ... various shared operators etc.
    double zero() const; // only want Polynomial<1> to support this
    // only want Polynomial<2> and Polynomial<1> to support the following
    //     because the solutions rapidly become too difficult to implement
    std::vector<double> zeros() const;
    std::vector<double> stationaryPoints() const { return derivative().zeros();}
private:
    std::array<double,2> coeffs;
}

我目前的解决方法是只从Polynomial<N>::zeros()中抛出异常以进行N>2,但是在编译时检测问题会很好。

你也可以使用 std::enable_if 来消除零函数。

template< int I >
class Poly {
public:
    template<int Ib = I, typename = std::enable_if_t<Ib == 1> > 
    double zero() 
    {
        return 42;
    }
};
int main()
{
    Poly< 10 > does_not_compile;
    does_not_compile.zero();
    //Poly< 1 >  compile;
    //compile.zero();
}
可以使用

CRTP 在知道派生基类的基类中实现zeroszero

然后有条件地从具有zeros和/或zero或没有的推导。

template<class P>
struct zeros { /* todo */ };
template<class P>
struct zero:zeros<P> { /* todo */ };
struct nozero {};
template<int N>
struxt Polynomial:
  std::conditional_t<
    (N==1),
    zero<Polynomial<N>>,
    std::conditional_t<
      (N==2),
      zeros<Polynomial<N>>,
      nozero
    >
  >
{
  // body
};

您的解决方案是模板专用化,在本例中为完全专用化。

但是,我认为您需要考虑您的设计。通常,为不同的情况定义不同的接口不是一个好主意,因为您没有利用抽象。

例如,考虑一下你的 stationaPoints() 函数。此函数不适用于多项式<2>因为导数是多项式<1>它没有 zeros() 函数。您的解决方案是将零函数添加到多项式<1>以使接口均匀化。

对于您的情况,我想您想要一个解决方案,该解决方案在多项式类型中包含 N-1 c 向量,其中包含零和一个零 (i) 函数来获取它们。像这样:

template <int N>
class Polynomial {
    double _coefs[N+1];
    double _zeros[N];
public:
    double zero(size_t i) const { assert(i<N); return _zeros[i]; }
    // ...
};

在这种情况下,您可以决定计算 de 零的策略,具体取决于您的应用程序:构造函数?,添加一个布尔值以了解它是否已计算,然后在第一次调用零时计算它,等等......

我想这个解决方案对你来说可能更有趣,因为如果你更喜欢 c 向量来存储系数,你不会喜欢你的 zeros() 函数的基于向量的接口,对吧?