我一直在利用空闲时间进行信号处理,并且正在编写自己的 DSP 库作为学习练习。我写了一个函数来计算 vector 的离散傅立叶变换。该函数有两个重载:一个用于 const std::vector<float> &
, 另一个是 std::vector<std::complex<float>>
.
我想让它更通用。该函数应该接受一对通用随机访问迭代器,而不是 vector 。然后,编译器应从迭代器中推断出它是复数数据还是实值数据,并选择正确的重载。
这应该给你一个想法,
//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
//...
}
最佳答案
好吧,只需删除 Container 和 T 模板参数,并只采用迭代器类型;这就是所有标准库算法(例如 <algorithm>
)所做的。然后使用 std::iterator_traits
得到T
作为迭代器的 value_type
.
现在,对于您的特化,您可以使用以下之一:
-
std::enable_if_t
- 标记派送
- constexpr-if - 因此对于这两种情况,您将拥有具有两个作用域的相同函数。
在这个问题中:
if constexpr instead of tag dispatch
您将在问题中看到如何使用第二个选项(标记的分派(dispatch))的示例,以及在其中一个答案中如何将其转换为 constexpr-if 的示例。
关于c++ - 给定类型为 Container<T>::Iterator 的函数参数,我如何实现特定类型 T 的特定重载?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50399165/