给定一个类型为 Container:<T>:Iterator 的函数参数,如何为某些类型的 T 实现特定的重载?
Given a function parameter of type Container<T>::Iterator, how do I achieve a specific overload for certain kinds of T?
我一直在空闲时间干预信号处理,我正在编写自己的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
//...
}
好吧,只需删除容器和 T 模板参数,只采用迭代器类型; 这就是所有标准库算法(例如在<algorithm>
中)所做的。然后使用std::iterator_traits
获取T
作为迭代器的value_type
。
现在,对于您的专业化,您可以使用以下之一:
std::enable_if_t
- 标记的调度
- constexpr-if - 因此,对于这两种情况,您将具有具有两个作用域的相同函数。
在这个问题中:
如果 constexpr 而不是标签调度
您将在问题中看到如何使用第二个选项(标记的调度)的示例,以及如何在其中一个答案中将其转换为constexpr-if的示例。
相关文章:
- 使用简单类型列表实现的指数编译时间.为什么
- 实现有界基元类型的c++
- 根据C++标准的定义实现"is_similar"类型特征
- 为什么 std::lerp 不适用于任何已实现所需操作的类型?
- C ++类型特征:确保子类实现方法
- 为自定义打印调试实现传递任何类型的变量
- 为 Sql 服务器实现 odbc 包装器.将数据库数据读取为字符或要求驱动程序将数据转换为 C 类型
- 将C++子类成员函数(虚拟实现)传递给 C 类型函数指针
- 使用智能指针指向 C 库中的结构,该结构通过 typedef 隐藏实现(即不完整的类型)
- 在 OpenCL 内核中实现半精度浮点数据类型
- 在头文件中使用opencv类型来实现未定义的标识符
- 如何实现对参数顺序不可知的std::same_as的广义形式(即对于两个以上的类型参数)
- 在 C++11 标准中,为什么要依赖 char 类型实现?
- 为容器中的不同字符串类型实现编译时"static-if"逻辑
- 用TR1 :: Shared_ptr类型实现std ::相等
- C void*任何类型实现都会返回奇怪的结果
- C :执行模板类型实现方法
- C++基于运行时类型实现强制转换
- Qt:如何为所有小部件和小部件类型实现通用基类信号/插槽功能(通过虚拟基类插槽)
- C++具有自定义类的泛型类型实现