1

我写了一个模板类,它应该适用于 double 和 std::complex。正如假设的那样,我所有的方法都在 .hpp 文件中。除了一个。我必须专门研究一种方法,因为在某些地方我必须计算 double 的平方或 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

4 回答 4

3

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

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));
}
于 2013-04-03T09:09:44.337 回答
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); }

然后,可以与 adouble和 a一起使用的通用代码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);
}

将输出:

4
13

这是一个活生生的例子

于 2013-04-03T09:15:14.587 回答
1

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

26.4.9附加重载 [cmplx.over]
以下函数模板应具有附加重载: arg norm conj proj imag real
附加重载应足以确保:

  1. 如果参数的类型为 long double,那么它会被有效地强制转换为复数。
  2. 否则,如果参数的类型为 double 或整数类型,则它被有效地转换为 complex<double>。
  3. 否则,如果参数的类型为浮点数,那么它会被有效地转换为复数。

这应该有效(并且在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';
}
于 2013-04-03T11:29:59.720 回答
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 或(内联时)在您的头文件中。

于 2013-04-03T09:17:13.763 回答