c++ iterator_category和iterator_concept的区别是什么?

dm7nw8vv  于 2023-10-21  发布在  Go
关注(0)|答案(1)|浏览(111)

C20带来了更强大的iterator系统,其中之一就是在iterator_category的基础上引入了iterator_concept
我发现C
20中很多迭代器的iterator_conceptiterator_category不一致。以最著名的iota_view作为example

using R = decltype(views::iota(0));
static_assert(random_access_range<R>);

using I = ranges::iterator_t<R>;
static_assert(same_as<typename I::iterator_category, input_iterator_tag>);
static_assert(same_as<typename I::iterator_concept,  random_access_iterator_tag>);

虽然R模型为random_access_range,但其迭代器的iterator_category只是input_iterator_tag,这与iterator_concept不一致。
C20为什么要引入iterator_concept?它的目的是什么?如果我实现了自己的迭代器,如何正确定义iterator_conceptiterator_categoryiterator_category在C20中仍然有意义吗?

x7rlezfr

x7rlezfr1#

C17(C98)迭代器模型和C++20 Ranges迭代器模型之间存在不向后兼容的差异。这两个大问题是:

  1. C++98模型要求前向迭代器的referencevalue_type&value_type const&
  2. C98模型不允许contiguous迭代器。最强的类别是random_access
    (1)的结果是相当重要的-它意味着如果你有一个返回纯右值的迭代器(无论是否是代理引用),它永远不会比输入迭代器更强。因此,views::iota(1, 10)尽管很容易就能支持随机访问,但充其量只是一个C
    98输入范围。
    但是,你不能只是...取消这一要求。假设C98迭代器并使用iterator_category进行判断的现有代码完全有权假设如果iterator_categorybidirectional_iterator_tag,则其referencevalue_type的某种左值引用。
    iterator_concept所做的是添加一个新的C
    20层,允许迭代器既通告其C98/17类别,又明显地通告其C20类别。所以回到iota_view<int, int>的例子,该视图的迭代器将iterator_category设置为input_iterator_tag(因为reference是纯右值,所以它不满足偶数向前的旧要求),但其iterator_concept设置为random_access_iterator_tag(因为一旦我们放弃该限制,我们可以轻松支持所有随机访问限制)。
    iterator.concepts.general(https://eel.is/cdraft/iterator.concepts.general)中,我们有一个神奇的函数ITER_CONCEPT(I),它可以帮助我们确定在C20中使用什么标记。
    (2)的问题是,由于各种C++98/17代码会检查该标记的方式(许多代码可能会检查random_access_iterator_tag),因此很难添加新的contiguous_iterator_tagiterator_concept方法还引入了一些概念,可以直接为您检查正确的事情(即,random_access_iterator概念检查ITER_CONCEPT(I)是从random_access_iterator_tag派生而来的,而不是简单的那样)。
    指导原则:
  • 如果你在C++17中使用迭代器,请使用std::iterator_traits<I>::iterator_category
  • 如果你在C++20中使用迭代器,请使用std::meow_iterator概念
  • 如果你在C++17中 * 写 * 一个迭代器,添加iterator_category别名,并确保你遵循前向迭代器/引用限制(或...不要,但这是你的)
  • 如果你在C++20中 * 编写 * 迭代器,请遵循P2259中的指导,其中对问题以及如何以及何时提供iterator_categoryiterator_concept类型别名有很好的描述。

相关问题