使用类型特征的部分 class 专业化

Partial class specialization using type traits

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

我有一个 class Polynomial 的定义:

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

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

然后我想,应该可以创建 Polynomial class 的部分特化,即对 class 进行浮点特化,其中一个是整数和复数。类似于

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

然而,不管我怎么做,它似乎永远都行不通。

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

希望能帮到你

您需要一个单独的基础 class 用于通用内容,然后您可以像这样为 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> {};

来不及玩了?

显然,您可以通过专业化解决问题,krisz 的回答显示了一种可能的方法。

但是你可以通过SFINAE简单地enabling/disablingintegral()解决

您无法检查 C 类型,因为 SFINAE 处理特定于该方法的模板,而不是 class 的模板,因此您必须使 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
 }

此解决方案的问题是,如果您显式 D 类型

,则可以 "hijacked"
   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