使用类型特征的部分类专门化

时间:2018-06-16 00:34:56

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

我是C ++的新手,我遇到了一个似乎无法解决的问题,或者找到了遇到同样问题的其他人。

我定义了一个类Polynomial

template<class C>
class Polynomial {
    std::vector<C> coefficients;
    ...
public:
    ...
    const double integral(double, double);
    ...
};

我需要确保,如果integral()是一个整数类型,则无法调用C方法。显然这意味着使用类型特征,但是我已经尝试在方法本身上使用template<typename = typename std::enable_if<!std::is_integral<C>::value, C>::type>,虽然它会编译,但我现在不能使用整数类型作为模板参数。

然后我想,应该可以创建Polynomial类的部分特化,即具有浮点的类的特化,一个具有整数,一个具有复数。

的内容
template<typename C>
class Polynomial<typename std::enable_if<std::is_floating_point<C>::value, C>::type> : Polynomial<C> {
public:
    const double integral(double, double);
};

但是,无论我怎么做,它似乎永远不会起作用。

我想我的问题是:如何使用类型特征作为特化来指定类的部分特化?

我希望你能提供帮助。

2 个答案:

答案 0 :(得分:3)

您需要为常见内容提供单独的基类,然后您可以像Polynomial那样为template<class C> class PolynomialBase { std::vector<C> coefficients; }; template <typename T, typename Enable = void> class Polynomial; template<typename C> class Polynomial<C, typename std::enable_if<!std::is_integral<C>::value>::type> : PolynomialBase<C> { public: const double integral(double, double); }; template<typename C> class Polynomial<C, typename std::enable_if<std::is_integral<C>::value>::type> : PolynomialBase<C> {}; 创建模板专业化:

CREATE TABLE AS SELECT

答案 1 :(得分:3)

玩的已经太晚了?

显然,你可以通过专业化解决问题,而克里斯的答案显示出一种可能的方式。

但您可以通过SFINAE简单地启用/禁用integral()来解决此问题。

您无法检查C类型,因为SFINAE适用于特定于该方法的模板,而非该类,因此您必须使integral()成为模板方法。

以示例

  template <typename D = C>
  std::enable_if_t<std::is_floating_point<D>::value, double>
     integral (double, double)
   { return 1.0; }

这样您就可以检查D类型默认的C类型。

以下是完整的编译示例

#include <vector>
#include <type_traits>

template <typename C>
class Polynomial
 {
   private:
      std::vector<C> coefficients;

   public:
      template <typename D = C>
      std::enable_if_t<std::is_floating_point<D>::value, double>
         integral (double, double)
       { return 1.0; }
 };

int main()
 {
   Polynomial<float>  pf;
   Polynomial<int>    pi;

   pf.integral(0.0, 0.0);  // compile

   // pi.integral(0.0, 0.0);  // compilation error
 }

这个解决方案的问题是可以被劫持&#34;如果您明确D类型

   Polynomial<int>    pi;

   // pi.integral(0.0, 0.0);  // compilation error

   pi.integral<double>(0.0, 0.0); // hijacked: compile

为避免劫持问题,您可以修改integral()的SFINAE测试,同时强调CD是同一类型

所以如果你按如下方式写的话

  template <typename D = C>
  std::enable_if_t<std::is_floating_point<D>::value
                && std::is_same<C, D>::value, double>
     integral (double, double)
   { return 1.0; }

integral()无法再被劫持

    Polynomial<int>    pi;

   // pi.integral(0.0, 0.0);  // compilation error

   // pi.integral<double>(0.0, 0.0); // compilation error