【问题标题】:Templated class: Check if complex at compile time模板类:在编译时检查是否复杂
【发布时间】:2015-08-24 13:27:38
【问题描述】:

我有一个A 模板化的类Scalar,它可以是实值或复值。它有一个方法realPart,它应该返回数字的实部。如果Scalar 是实值,它应该只返回原始标量,如果它是复杂类型,则返回.real()

写作时

#include <complex>
#include <iostream>

template<class Scalar>
class A {
  public:
    A (const Scalar z):
      z_(z)
    {
    }

    Scalar realPart()
    {
      return z_.real();
    }

  private:
    Scalar z_;
};

int main() {
  A<std::complex<double>> z0((1.0, 2.0));
  std::cout << z0.realPart() << std::endl; // check

  A<double> z1(1.0);
  std::cout << z1.realPart() << std::endl; // mööp
}

编译器会在z1.realPart() 抱怨,因为double 不知道.real()

如何在编译时保护.real()

【问题讨论】:

  • 你到底想用 double 发生什么?
  • 您可以为复杂类型创建模板特化。
  • @DavidHaim 在double 的情况下,只需return z_,就像你在数学上所期望的那样。
  • 就像@AkashPradhan 说的为它创建一个模板专业化。
  • 查看带有类型特征的stackoverflow模板条件stackoverflow.com/questions/6251889/type-condition-in-template

标签: c++ templates complex-numbers


【解决方案1】:

这可以通过一个简单的is_complex trait 和 SFINAE 来完成:

template<class T> struct is_complex : std::false_type {};
template<class T> struct is_complex<std::complex<T>> : std::true_type {};

template<class Scalar>
class A {
public:
    A(const Scalar z) : z_(z)
    { }

    template<class S = Scalar, std::enable_if_t<is_complex<S>{}>* = nullptr>
    Scalar realPart()
    {
      return z_.real();
    }

    template<class S = Scalar, std::enable_if_t<!is_complex<S>{}>* = nullptr>
    Scalar realPart()
    {
      return z_;
    }
private:
    Scalar z_;
};

【讨论】:

  • 为什么需要 S 类模板参数?你不能使用 is_complex 吗?
  • @Eugene 替换失败必须发生在模板的即时上下文中。整个类的“外部”模板不是成员函数模板的直接上下文。所以我们使用一个虚拟参数来给它起别名。
  • 添加#include &lt;type_traits&gt;#include &lt;complex&gt; 后,我得到‘std::enable_if_t’ has not been declared。这是 GCC 5.1.1。有什么我忘了补充的吗?
  • enable_if_t 是 c++14。它相当于typename std::enable_if&lt;T&gt;::type - 请参阅en.cppreference.com/w/cpp/types/enable_if
猜你喜欢
  • 1970-01-01
  • 2022-01-31
  • 2014-03-31
  • 1970-01-01
  • 1970-01-01
  • 2013-10-02
  • 1970-01-01
  • 2011-05-09
  • 1970-01-01
相关资源
最近更新 更多