How to avoid the built-in `std :: complex` when providing` T = std :: complex <Q> `?

To solve the polynomial equation, it would be great to create a template for access to any type:

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

This allows you to use, for example, double in used for input, and the result is std::complex<double> in โ„‚ (we know that from degree 2 or more the solution of the equation usually falls into โ„‚, for example: x ^ 2 + 1).

But the input to the equation can also be a std::complex . In this case, the type myEquation should be complex, but equationResult should NOT be std::complex<complex<T>> , but simply a normal complex number of type T

Questions:

How to make the equationResult type a subtype of std::complex when the equation is supplied with std::complex ?

Is there an equivalent to std::is_floating_point such as std :: is_complex_number?

+6
source share
4 answers

You can create traits, for example:

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

And then

 template <class number, int degree> class PolynomialEquation { public: private: array<number, degree+1> myEquation; array<typename to_complex<number>::type, degree> equationResult; }; 
+7
source

I don't think there is a trait for checking if a type is a complex number, but it is relatively easy to create (also an alternative implementation of Jarod 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> } 
+2
source

Here's a single-line version of C ++ 14, alternative to @WF

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

It is assumed that if it is not an arithmetic type, then it must be complex. If you are not careful, you need to make sure that T is either arithmetic (or even a floating point) or complex. You will need to mix this with @WF anwser.

+2
source

I have a class of polynomials where I potentially needed real coefficients and complex x (as well as real, real and complex, complex). I did 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; 

In addition, I use tools to extract the scalar type, whether the input is scalar or complex, so I can use numerical constraints, for example:

 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; 

which I could use as follows:

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

and then build convergence tests for both real and complex inputs.

+1
source

All Articles