c++ - 定义transform_view::iterator的iterator_category的问题?
问题描述
该标准在[range.adaptors]中定义了各种范围适配器,其中一些具有自己的迭代器类型。
为了标准化iterator_category
这些迭代器,该标准还指定了它们的定义方式。例如,在[range.transform.iterator-2]中,iterator_category
oftransform_view::iterator
的定义如下:
当且仅当models 定义成员typedef-name 。在这种情况下, 定义如下:让表示类型。
iterator_category
Base
forward_range
iterator::iterator_category
C
iterator_traits<iterator_t<Base>>::iterator_category
如果
is_lvalue_reference_v<invoke_result_t<F&, range_reference_t<Base>>>
是true
,那么
如果
C
模型derived_from<contiguous_iterator_tag>
,iterator_category
表示random_access_iterator_tag
;否则,
iterator_category
表示C
。否则,
iterator_category
表示input_iterator_tag
。
但是这个定义似乎有一些问题,考虑以下情况:
vector v{1, 2, 3, 4, 5};
auto r = views::iota(0, 5) |
views::transform([&](int i) -> int& { return v[i]; });
using I = ranges::iterator_t<decltype(r)>;
static_assert(random_access_iterator<I>);
static_assert(same_as<I::iterator_concept, random_access_iterator_tag>);
static_assert(__detail::__cpp17_randacc_iterator<I>);
static_assert(same_as<I::iterator_category, input_iterator_tag>);
由于在 C++20 中r
是完美的,它的迭代器模型,然而,根据上面的描述,由于is only ,迭代器的 也是 only 。random_access_range
random_access_iterator
iota_view::iterator_category
input_iterator_tag
iterator_category
I
input_iterator_tag
但是很明显,iteratorI
满足了 的所有要求,所以如果它的isLegacyRandomAccessIterator
应该更合理。iterator_category
random_access_iterator
这是标准缺陷吗?还是这背后有考虑?
解决方案
根据 C++20,a 的迭代器类别transform_view
确定如下:
iterator::iterator_category
定义如下:C
表示类型iterator_traits<iterator_t<Base>>::iterator_category
。
- 如果
is_lvalue_reference_v<invoke_result_t<F&, range_reference_t<Base>>>
是真的,那么
- 如果
C
模型derived_from<contiguous_iterator_tag>
,iterator_category
表示random_access_iterator_tag
;- 否则,
iterator_category
表示C
。- 否则,
iterator_category
表示input_iterator_tag
。
因此,如果您的仿函数返回左值引用,则迭代器类别派生自基本迭代器类型的迭代器类别。提供基本迭代器的基本范围是views::iota
.
但是,因为iota
是纯右值范围(它的迭代器返回纯右值,而不是引用),所以它 iterator_category
不能是std::input_iterator_tag
. 所以在上面的文字中transform_view
,C
将是std::input_iterator_tag
。所以无论你的函子返回什么,类别transform_view
都会是。std::input_iterator_tag
您应该真正避免关心iterator_category
何时使用std::ranges
基于 - 的代码。如果您知道您正在处理 C++20 范围,那么您应该使用iterator_concept
.
推荐阅读
- code-coverage - 如何使用 nyc 完全删除 lcov-report 的部分?
- c - 如何创建引用位于链表中的结构中的双精度的原型?
- javascript - 如何下载 HTML5 画布的背景图像?
- azure-data-explorer - 日期时间与字符串连接
- mysql - 将 NOW() 转换为 dmY
- python - 类最佳实践 - 没有参数的方法与属性覆盖本身
- mongodb - MongoDB 中 db.currentOp() 输出中的奇怪操作
- javascript - 错误:尝试 setState 时重新渲染过多
- android - 如何在 NavigationDrawer 中正确地将项目标记为选中?
- google-data-studio - 在谷歌数据工作室编辑数据透视表