класс — шаблон c ++ double std :: complex & lt; double & gt; норма и продукт

я написал шаблонный класс, который должен работать для double и std :: complex. как и должно быть, все мои методы находятся в файле .hpp. все кроме одного. Я должен был специализировать метод, потому что в каком-то месте я должен вычислить квадрат двойного или норма std :: complex. более явно для «двойной специализации» (A):

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

для «комплексной специализации» (Б):

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

мои вопросы:

  • Есть ли способ избежать этих специализаций, используя функцию, которая работает как для двойных, так и для сложных? (потому что std :: norm работает только для сложных …)

  • или единственное решение состоит в том, чтобы преобразовать двойную специализацию (A) в комплекс, а затем использовать только специализацию (B) в качестве общего шаблона (работая как для двойной, так и для сложной)?

0

Решение

Вы можете свести к минимуму расходящийся случай, введя свою собственную функцию в качестве обертки для квадрата / нормы:

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

Другие решения

Вы можете определить две функции шаблона перегрузки (когда дело доходит до шаблонов функций, перегрузка обычно предпочтительнее специализация) называется 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);
}

Будет выводить:

4
13

Вот живой пример.

1

Если у вас есть соответствующая стандартная библиотека, существует перегрузка std::norm для типов с плавающей точкой:

26.4.9 Дополнительные перегрузки [cmplx.over] Следующие шаблоны функций должны иметь дополнительные перегрузки:
arg norm
conj proj
imag real

Дополнительные перегрузки должны быть достаточными для обеспечения:

  1. Если аргумент имеет тип long double, то он фактически приводится к сложному.
  2. В противном случае, если аргумент имеет тип double или целочисленный тип, он фактически приводится к сложному<
    двойной>.
  3. В противном случае, если аргумент имеет тип float, он фактически приводится к комплексу.

Это должно работать (и делает на 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';
}
1

Почему бы просто не использовать перегрузку функций?

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 или (если он встроен) в ваш заголовочный файл.

0
По вопросам рекламы [email protected]