繁体   English   中英

定义transform_view ::iterator的iterator_category的问题?

[英]The problem of the definition of transform_view​::iterator's iterator_category?

该标准在[range.adaptors] 中定义了各种范围适配器,其中一些具有自己的迭代器类型。

为了规范这些迭代iterator_category的iterator_category,标准还规定了它们是如何定义的。 例如,在[range.transform.iterator-2]中, iterator_categorytransform_view​::​iterator定义如下:

当且仅当Base模型forward_range时才定义成员typedef-name iterator_category 在这种情况下, 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>);

由于r在 C++20 中是完美的random_access_range ,它的迭代器模型random_access_iterator ,但是,根据上面的描述,由于iota_view::iterator_category只是input_iterator_tag ,因此iterator_categoryI的 iterator_category 也只有input_iterator_tag

但显然,迭代器I满足LegacyRandomAccessIterator所有要求,所以它的iterator_categoryrandom_access_iterator应该更合理。

这是标准缺陷吗? 或者这背后有什么考量?

根据 C++20, 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无论您的函子返回什么

当您使用基于std::ranges的代码时,您真的应该避免关心iterator_category 如果您知道您正在处理 C++20 范围,那么您应该使用iterator_concept

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM