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

时间:2016-07-13 06:58:48

标签: c++ templates c++11

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

// 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抛出异常,但在编译时检测问题会很好。

3 个答案:

答案 0 :(得分:1)

您也可以使用std::enable_if远离SFINAE零功能。

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();
}

答案 1 :(得分:0)

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

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

例如,考虑一下你的stationaPoints()函数。 Polynomial&lt; 2&gt;不能使用此功能。因为衍生物是多项式&lt; 1&gt;。它没有zeros()函数。您的解决方案是将零函数添加到多项式&lt; 1&gt;。为了使界面均匀化。

对于你的情况,我想你想要一个解决方案,其中包含多项式类型中的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 zeros的策略,具体取决于你的应用程序:constructor ?,添加一个布尔值来知道它是否已经计算,然后在第一次调用零时计算,等等......

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

答案 2 :(得分:0)

您可以使用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
};