在提供"T=std::complex"时如何避免嵌入"std::complex<Q>"?

How to avoid embedded `std::complex` when providing `T=std::complex<Q>`?

本文关键字:complex std lt gt 何避免      更新时间:2023-10-16

对于多项式方程求解器,最好将其模板化为具有任何可用类型:

template <class number, int degree>
class PolynomialEquation
{
public:
private:
    array<number, degree+1> myEquation;
    array<complex<number>, degree> equationResult;
};

例如,这允许将R中的double用于输入,并将结果std::complex<double>在C中(我们知道,从2度及以上,方程的解通常落入C,例如:x^2 + 1(。

但是,等式的输入也可能是一个std::complex 。在这种情况下,myEquation的类型应该是复数,但equationResult不应该是std::complex<complex<T>>,而只是T型的普通复数。

问题:

当方程提供std::complex时,如何使equationResult的类型成为std::complex的子类型?

有没有像 std::is_complex_number 这样的std::is_floating_point等价物?

您可以创建一个特征,如下所示:

template <typename T>
struct to_complex {
    using type = std::complex<T>;
};
template <typename T>
struct to_complex<std::complex<T>> {
    using type = std::complex<T>;
};

然后

template <class number, int degree>
class PolynomialEquation
{
public:
private:
    array<number, degree+1> myEquation;
    array<typename to_complex<number>::type, degree> equationResult;
};
我认为检查

类型是否为复数没有特征,但创建一个应该相对容易(也是 Jarod's to_complex 的替代实现(:

#include <type_traits>
#include <complex>
#include <iostream>
template <class T>
struct is_complex_number: std::false_type { };
template <class T>
struct is_complex_number<std::complex<T>>: std::true_type { };
template <class T>
struct to_complex: std::conditional<is_complex_number<T>::value, T, std::complex<T>> { };
int main() {
   std::cout << is_complex_number<float>::value << std::endl; // output: 0
   std::cout << is_complex_number<std::complex<float>>::value << std::endl; // output: 1
   typename to_complex<float>::type c; // decltype(c) == complex<float>
   typename to_complex<std::complex<float>>::type d; // decltype(d) == complex<float>
}

我有一个多项式类,我可能想要实系数和复数x(以及实数,实数和复数,复数(。 我做了一个is_complex:

/**
 * Introspection class to detect if a type is std::complex.
 */
template<typename _Tp>
  struct is_complex : public std::false_type
  { };
/**
 * Introspection class to detect if a type is std::complex.
 */
template<>
  template<typename _Tp>
    struct is_complex<std::complex<_Tp>> : public std::true_type
    { };
/**
 * Introspection type to detect if a type is std::complex.
 */
template<typename _Tp>
  using is_complex_t = typename is_complex<_Tp>::type;
/**
 * Introspection variable template to detect if a type is std::complex.
 */
template<typename _Tp>
  constexpr bool is_complex_v = is_complex<_Tp>::value;
此外,我

使用工具来提取标量类型,无论输入是标量还是复杂,因此我可以使用数字限制工具,例如:

template<typename Tp>
  struct num_traits
  {
    using __value_type = Tp;
  };
template<>
  template<typename Tp>
    struct num_traits<std::complex<Tp>>
    {
      using __value_type = typename std::complex<Tp>::value_type;
    };
template<typename Tp>
  using num_traits_t = typename num_traits<Tp>::__value_type;

我可以像这样使用:

  using Val = num_traits_t<Ret>;
  constexpr auto eps = std::numeric_limits<Val>::epsilon();

并随后为真实和复杂输入构建收敛测试。

这是 @W.F 的 C++14 单行替代。

using Complex = typename std::conditional<std::is_arithmetic<T>::value, std::complex<T>, T>::type;

假设是,如果它不是算术类型,那么它应该是一个复杂的类型。如果你不想彻底,你需要确保T要么是算术(甚至是浮点数(要么是复数。您需要将其与@W.F. anwser混合使用。