c ++ template double std :: complex <double> norm and product </double>

时间:2013-04-03 09:02:52

标签: c++ class templates std norm

我写了一个模板类,应该适用于double和std :: complex。正如它所假设的那样,我的所有方法都在.hpp文件中。除了一个。我必须专门化一个方法,因为在某些地方我必须计算一个双的平方或std :: complex的范数。更明确的“双重专业化”(A):

double a(2.0);
double b(0.0);
b = a*a;

用于“复杂专业化”(B):

std::complex<double> a(2.0,3.0);
double b(0.0);
b = std::norm(a);

我的问题是:

  • 有没有办法通过使用适用于double和complex的函数来避免这些特化? (因为std :: norm仅适用于复杂的......)

  • 或唯一的解决方案是将专业化(A)的双重a转换为复合体,然后仅使用特化(B)作为通用模板(同时用于复合和复合)?

4 个答案:

答案 0 :(得分:2)

您可以通过将自己的函数作为平方/范数包装器来最小化不同情况:

template <typename T>
double square_or_norm(T x);

template<>
inline double square_or_norm(double x) { return x * x; }

template <>
inline double square_or_norm(std::complex<double> x) { return norm(x); }

然后,在需要它的函数中使用它:

template <typename T>
T computation(T x) {
  return some_code_with(x, square_or_norm(x));
}

答案 1 :(得分:1)

您可以定义两个函数模板重载(当涉及到函数模板时,重载通常比 specialization 更可取)称为{{1一个接受compute_norm(),一个接受无约束类型。无约束模板将调用std::complex,而受约束的模板将调用operator *

std::norm()

然后,您的通用代码可以使用#include <complex> template<typename T> double compute_norm(T t) { return t * t; } template<typename T> double compute_norm(std::complex<T> const& t) { return std::norm(t); } double同时调用complex<double>

compute_norm()

例如,以下程序:

#include <iostream>

template<typename T>
void foo(T&& t)
{
    // ...
    double n = compute_norm(std::forward<T>(t));
    std::cout << n << std::endl;
    // ...
}

将输出:

int main()
{
    double a(2.0);
    foo(a);

    std::complex<double> c(2.0, 3.0);
    foo(c);
}

这是live example

答案 2 :(得分:1)

如果您有一个符合标准的库,浮点类型的重载次数为std::norm

  

26.4.9 其他重载[cmplx.over]
  以下函数模板应具有其他重载:       arg norm conj proj imag real
  额外的过载应足以确保:

     
      
  1. 如果参数的类型为long double,那么它将被有效地转换为复数。
  2.   
  3. 否则,如果参数具有double类型或整数类型,则它有效地转换为complex&lt;   双&GT;
  4.   
  5. 否则,如果参数的类型为float,那么它将被有效地转换为complex。
  6.   

这应该有效(并在gcc 4.7.2上执行)

#include <complex>
#include <iostream>

int main()
{
    std::complex<double> c {1.5, -2.0};
    double d = 2.5;

    std::cout << "|c| = " << std::norm(c) << '\n'
              << "|d| = " << std::norm(d) << '\n';
}

答案 3 :(得分:0)

为什么不直接使用函数重载?

double myNorm(double);
double myNorm(std::complex<double>);


double myNorm(double x) {
    return x * x;
}
double myNorm(std::complex<double> x) {
    return std::norm(x);
}

您可以将实现放在头文件中的.cpp或(内联时)。