[libcxx-commits] [PATCH] D129794: [libc++] Fix reverse_iterator::iterator_concept

Hui via Phabricator via libcxx-commits libcxx-commits at lists.llvm.org
Thu Jul 14 13:01:28 PDT 2022


huixie90 accepted this revision.
huixie90 added a comment.

LGTM with nits



================
Comment at: libcxx/test/support/test_iterators.h:227
+
+template <class It>
+class cpp20_random_access_iterator {
----------------
perhaps constrain `It` to be at least `random_access_iterator`?


================
Comment at: libcxx/test/support/test_iterators.h:235-240
+  using iterator_category = std::input_iterator_tag;
+  using iterator_concept  = std::random_access_iterator_tag;
+  using value_type        = typename std::iterator_traits<It>::value_type;
+  using difference_type   = typename std::iterator_traits<It>::difference_type;
+  using pointer           = It;
+  using reference         = typename std::iterator_traits<It>::reference;
----------------
This is more of FYI and you don't have to follow. To define new C++20 iterators with some level of c++17 backward compatibility support, we typically define:
- `iterator_category` if the class we define does model c++17 iteartor
- `iterator_concept`. this is obvious
- `value_type` for `indirectly_readable_traits`
- `difference_type` for `incrementable_traits`

We actually don't want to define `pointer` and `reference`. For C++20 concepts, they are not needed, they are deduced from `operator->` (if exists) and `operator*`. For C++17 backward compatibility, by not defining them, it will trigger the primary template `iteartor_traits` to properly generate them from `operator*` and `operator->` if they exist.

By defining them it will change the rule of `iterator_traits` primary template.

So the above is what we typically do when writing proposals for new range adaptors


================
Comment at: libcxx/test/support/test_iterators.h:248
+
+  template <class U, class = typename std::enable_if<std::is_default_constructible<U>::value>::type>
+  constexpr cpp20_random_access_iterator(cpp20_random_access_iterator<U>&& u) : it_(u.it_) {
----------------
if `U` itself already models `random_access_iterator`, it is already default constructible. If not, then perhaps some of the member functions will be broken. Do we need to check here?


================
Comment at: libcxx/test/support/test_iterators.h:253
+
+  constexpr reference operator*() const { return *it_; }
+  constexpr reference operator[](difference_type n) const { return it_[n]; }
----------------
Again you don't have to do. A really common category of iterators that model c++20 randam_access_iterator but only c++17 input_iterator are iterators with prvalue `reference` type, such as `iota`, `transform` iterator with `F` return by value. If I wrote this class, I'd simulate that. but you don't have to


================
Comment at: libcxx/test/support/test_iterators.h:309
+  }
+
+  friend constexpr It base(const cpp20_random_access_iterator& i) { return i.it_; }
----------------
This class defined `pointer` to be `It`, but not defining `operator->` , which is incorrect. I'd recommend just not define `pointer` since `operator->` isn't required


================
Comment at: libcxx/test/support/test_iterators.h:311
+  friend constexpr It base(const cpp20_random_access_iterator& i) { return i.it_; }
+
+  template <class T>
----------------
perhaps forward `iter_move` and `iter_swap` as well in case this class is used in the future by some other tests?


================
Comment at: libcxx/test/support/test_iterators.h:316
+
+static_assert(std::random_access_iterator<cpp20_random_access_iterator<int*>>);
+
----------------
perhaps also `static_assert` the `iterator_traits::iterator_category` is  not derived from random access tag?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D129794/new/

https://reviews.llvm.org/D129794



More information about the libcxx-commits mailing list