c++ - 给定类型为 Container<T>::Iterator 的函数参数,我如何实现特定类型 T 的特定重载?

标签 c++ templates parameter-passing fft c++17

我一直在利用空闲时间进行信号处理,并且正在编写自己的 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/

相关文章:

php - 如何消除 Smarty {block} 中的空格?

c++ - 不能通过引用 C++ 将参数用作无符号整数

java - 如何将参数传递给 HttpServer 的实现?

c++ - Qt Creator 编辑器中的高 CPU 使用率

c++ - C++模板中的百分号(%)和尖锐符号(#)是什么意思

c++ - 无法从 Object 转换为 Int

c++ - 使用 numeric_limits 作为默认参数值

arrays - 在VBA中返回数组的函数

c++ - 如何检查 C++ 中的 std::map 插入是否失败?

c++ - WM_CTLCOLORSTATIC 永远不会在 WIN32 应用程序中触发