专门C++使用指针值类型的通用迭代器的模板函数?
Specialize C++ template function that uses generic iterators for pointer value type?
我有一个C++模板函数,它接受泛型迭代器作为参数,如下所示:
(它处理从first
到但不包括last
的所有元素(
void update(const std::uint8_t *const data, const size_t len)
{
/* ... */
}
template<typename iterator_type>
void update(const iterator_type &first, const iterator_type &last)
{
typedef typename std::iterator_traits<iterator_type>::value_type value_type;
for (iterator_type iter = first; iter != last; ++iter)
{
update(reinterpret_cast<const std::uint8_t*>(std::addressof(*iter)), sizeof(value_type));
}
}
到目前为止,这是有效的。我唯一的问题是:如果迭代器的value_type恰好是指针类型,则此函数处理指针值(内存地址(而不是指针指向的实际值(对象(。所以,我想专门处理指针类型。C++有没有一种好方法可以为value_type为指针类型的迭代器提供此模板函数的专用化?
我试图用一个函数和一个if(is_pointer)... else...
结构来解决这个问题,如下所示:
void update(const iterator_type &first, const iterator_type &last)
{
typedef typename std::iterator_traits<iterator_type>::value_type value_type;
if(std::is_pointer<value_type>::value)
{
for (iterator_type iter = first; iter != last; ++iter)
{
update(reinterpret_cast<const std::uint8_t*>(*iter), sizeof(std::pointer_traits<value_type>::element_type));
}
}
else
{
for (iterator_type iter = first; iter != last; ++iter)
{
update(reinterpret_cast<const std::uint8_t*>(std::addressof(*iter)), sizeof(value_type));
}
}
}
。但是,不幸的是,这不适用于非指针类型:
error C2039: 'element_type': is not a member of 'std::pointer_traits<value_type>'
编写模板函子来更新单个项目并对其进行专用化会更容易。然后,让更新模板函数调用该类。像这样:
template <typename T>
struct Update {
void operator () (const T &v) {
//...
}
};
template <typename T>
struct Update<T *> {
void operator () (const T *v) {
//...
}
};
template <typename T>
void update (const T &v) {
Update<T>()(v);
}
然后在循环中,你这样称呼它:
update(*iter);
您可以将更新函子参数化到更新函数模板中,以便在调用方想要执行与默认更新处理不同的操作时为其提供灵活性。
template <typename T, typename U = Update<T>>
void update (const T &v, U u = U{}) {
u(v);
}
然后,前面的调用仍然有效,但您也可以传入不同的可调用对象(如 lambda(。
update(*iter, [](int *){ /* ... */ });
这个问题已经有一个很好的答案,但我在这里提出类型特征和标签调度使得具有指针和非指针值类型的迭代器之间的重载变得容易:
template <typename T>
void update_tag_dispatch(T first, T last, std::true_type) {
std::cout << "iterator value is a pointer!n";
}
template <typename T>
void update_tag_dispatch(T first, T last, std::false_type) {
std::cout << "iterator value is not a pointern";
}
template <typename T>
void update_tag_dispatch(T first, T last) {
update_tag_dispatch(first, last, std::is_pointer<std::remove_reference_t<decltype(*first)>>{});
}
你也可以使用它的表亲,std::enable_if_t
:
template <typename T, std::enable_if_t<std::is_pointer<std::remove_reference_t<decltype(*std::declval<T>())>>::value>* = nullptr>
void update_enable_t(T first, T last) {
std::cout << "iterator value is a pointer!n";
}
template <typename T, std::enable_if_t<!std::is_pointer<std::remove_reference_t<decltype(*std::declval<T>())>>::value>* = nullptr>
void update_enable_t(T first, T last) {
std::cout << "iterator value is a pointer!n";
}
演示:https://godbolt.org/z/t7YbcF
相关文章:
- 如何在C++中将迭代器作为函数参数传递
- 如何在 c++ 中将字符串迭代器变量传递给函数?
- 为什么我的模板化函数需要从一个迭代器转换到另一个迭代器?
- 如何创建迭代器函数
- 为什么在指向对象的迭代器上调用函数不允许我更改对象本身?
- 迭代器库中的 std::size() 不适用于传递给函数的 C 样式数组
- 使用迭代器的模板类的构造函数
- C++:复制迭代器的构造函数
- 基于函数而不是集合的二分搜索或迭代器?
- 成员函数中的迭代器出现问题
- 使用迭代器的自定义比较器函数
- 专门C++使用指针值类型的通用迭代器的模板函数?
- 从 std::vector 迭代器中执行函数指针
- 调用 erase() 函数是否也会在擦除元素之前更改迭代器值?
- 如何基于循环迭代器选择函数
- 矢量迭代器在尝试调用函数时使我的程序崩溃
- 成员函数不能为集合迭代器和const_iterator的输入重载(但可以为其他 STL 迭代器重载)
- 具有C++迭代器参数的多功能函数
- C++如何获取传递给函数(STL 迭代器)的参数的名称
- C++ 对自定义映射迭代器函数的未定义引用