В свободное время я вмешивался в обработку сигналов и пишу свою собственную библиотеку DSP в качестве учебного упражнения.Я написал функцию, которая вычисляет дискретное преобразование Фурье вектора.Есть две перегрузки функции: одна для const std::vector<float> &
, а другая для std::vector<std::complex<float>>
.
Я бы хотел сделать это более общим.Вместо вектора функция должна принимать пару общих итераторов произвольного доступа.Затем компилятор должен определить из итераторов, являются ли они сложными или действительными данными, и выбрать правильную перегрузку.
Это должно дать вам представление,
//compute the discrete fourier transform in-place for a complex valued input
template<template<typename T> class Container, typename T, class RandomAccessIt>
void fft(
typename Container<std::complex<T>>::RandomAccessIt first,
typename Container<std::complex<T>>::RandomAccessIt last
)
{
...
}
//calculate the discrete fourier transform for a real valued input
template<template<typename T> class Container1,
template<std::complex<T>> class Container2,
typename T,
class RandomAccessIt1,
class RandomAccessIt2>
void fft(
typename Container1<T>::RandomAccessIt1 first,
typename Container1<T>::RandomAccessIt1 last,
typename Container2<std::complex<T>>::RandomAccessIt2 out_first
)
{
...
fft(...); //call the complex version
...
}
, но, как вы можете видеть, я действительно не знаю, что я делаю с шаблонами.Как я мог заставить это работать?Если это невозможно, то как?
РЕДАКТИРОВАТЬ:
Мне больше всего нравится if constexpr
-подход, поскольку он решает проблему довольно элегантно
template<typename T>
struct is_complex_t : public std::false_type {};
template<typename T>
struct is_complex_t<std::complex<T>> : public std::true_type {};
template<typename RandomAccessIt>
void fft(RandomAccessIt first, RandomAccessIt last)
{
using Number_t = typename std::iterator_traits<RandomAccessIt>::value_type;
if constexpr(!is_complex_t<Number_t>::value)
{
//math trickery to transform the real input data to complex-valued data
...
}
... //the FFT itself
if constexpr(!is_complex_t<Number_t>::value)
{
//math trickery to properly format the frequency domain data
...
}
}
Тем не менее, я имею спонял, что поскольку две перегрузки имеют разное количество параметров, мне даже не нужно никакого умного метапрограммирования :
//compute the discrete fourier transform in-place for a complex valued input
template<typename RandomAccessIt>
void fft(RandomAccessIt first, RandomAccessIt last)
{
//...
}
//calculate the discrete fourier transform for a real valued input
template<typename RandomAccessIt1, typename RandomAccessIt2>
void fft(
RandomAccessIt1 first, RandomAccessIt1 last,
RandomAccessIt2 out_first
)
{
//...
//fft(...); //call the complex version
//...
}