【发布时间】:2020-01-05 20:24:53
【问题描述】:
我有一个接受泛型迭代器作为参数的 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>'
【问题讨论】:
-
你的编译器支持 C++17 吗?如果是这样,只需将您的 if 更改为 if constexpr。有关详细信息,请参阅针对 C++17 更新的 C++ 书籍。
-
为了兼容性,代码应该用VS2010及更高版本(以及MinGW、GCC和Clang)编译,所以我更喜欢不使用C++17 - 仅功能。
-
如果有人打算使用该函数作用于指针怎么办?我认为与 std 库如何工作相一致的更清晰的解决方案是让调用者使用一些执行取消引用的迭代器适配器或让
update采用可选的转换 lambda。 -
在我的上下文中,如果调用者有一个指针容器(std::vector、std::list 等),那么处理指针(更多或更少的“随机”内存地址)作为数据;但是假设调用者实际上想要处理这些指针指向的数据是保存的。
标签: c++ visual-studio-2010 iterator function-templates