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

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

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

成员typedef-name iterator_­category当且仅当Basemodels 定义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是完美的random_access_range,它的迭代器模型random_access_iterator,但是,根据上面的描述,由于iota_view::iterator_category是 only input_iterator_tagiterator_category迭代器I的 也只有input_iterator_tag

但显然,迭代器I满足 的所有要求LegacyRandomAccessIterator,所以如果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_viewCstd::input_iterator_tag。因此,无论您的函子返回什么,for 的类别transform_view都是。std::input_iterator_tag

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

  • @康桓玮 是的,我明白你的意思。但是`static_assert(std::is_lvalue_reference_v&lt;std::filesystem::path::iterator::reference&gt;)`通过了,这并不意味着它满足[forward.iterators]6。很难制定一套相对简单的规则来确保符合该要求。

以上是定义transform_view?::iterator的iterator_category的问题?的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>