[libcxx-commits] [PATCH] D109086: [libc++] Implement ranges::filter_view

Konstantin Varlamov via Phabricator via libcxx-commits libcxx-commits at lists.llvm.org
Fri Apr 1 16:58:56 PDT 2022


var-const requested changes to this revision.
var-const added a comment.
This revision now requires changes to proceed.

Very close to LGTM. Most comments are optional (which includes all nits), but there's just a couple that I think are worth addressing.



================
Comment at: libcxx/include/__ranges/filter_view.h:48
+  class filter_view : public view_interface<filter_view<_View, _Pred>> {
+    _LIBCPP_NO_UNIQUE_ADDRESS __copyable_box<_Pred> __pred_;
+    _LIBCPP_NO_UNIQUE_ADDRESS _View __base_ = _View();
----------------
Nit: is there a reason to swap the order these are declared in, compared to the Standard? Not that it's an issue, but because of this, the constructor taking both of these parameters looks a little strange because the initialization order is the reverse of the argument order. Also, if there's a reason, I think it should be documented?


================
Comment at: libcxx/test/std/ranges/range.adaptors/range.filter/adaptor.pass.cpp:65
+constexpr bool test() {
+  int buff[8] = {0, 1, 2, 3, 4, 5, 6, 7};
+
----------------
Nit/question: why not let the number of elements to be deduced?


================
Comment at: libcxx/test/std/ranges/range.adaptors/range.filter/begin.pass.cpp:154
+    struct MutablePred {
+      constexpr bool operator()(int i) { return i % 2 == 0; }
+    };
----------------
Question: would it be worthwhile to test with a predicate that takes the argument by non-const reference?


================
Comment at: libcxx/test/std/ranges/range.adaptors/range.filter/ctad.pass.cpp:27
+
+// A range, but not a view
+struct Range {
----------------
Very optional: consider turning this comment into a static assertion instead.


================
Comment at: libcxx/test/std/ranges/range.adaptors/range.filter/ctor.default.pass.cpp:13
+// filter_view() requires std::default_initializable<View> &&
+//                        std::default_initializable<Pred> = default;
+
----------------
Same comment about potentially testing `noexcept` as another default constructor test.


================
Comment at: libcxx/test/std/ranges/range.adaptors/range.filter/ctor.view_pred.pass.cpp:78
+    Pred pred;
+    std::ranges::filter_view<TrackingRange, Pred> view(std::move(range), pred); (void)view;
+    assert(moved);
----------------
Nit: consider using `[[maybe_unused]]`.


================
Comment at: libcxx/test/std/ranges/range.adaptors/range.filter/iterator/compare.pass.cpp:13
+// friend constexpr bool operator==(iterator const&, iterator const&)
+//  requires equality_comparable<iterator_t<V>>
+
----------------
Optional: this seems untested.


================
Comment at: libcxx/test/std/ranges/range.adaptors/range.filter/iterator/compare.pass.cpp:35
+constexpr void test() {
+  using View = minimal_view<Iterator, Sentinel>;
+  using FilterView = std::ranges::filter_view<View, AlwaysTrue>;
----------------
Optional: perhaps these type aliases could be moved to `types.h` as well, along with `make_filter_view`. They seem to take a significant part of the setup in many of these test files.


================
Comment at: libcxx/test/std/ranges/range.adaptors/range.filter/iterator/compare.pass.cpp:73
+  {
+    static_assert(!has_equal<FilterIteratorFor<cpp20_input_iterator<int*>>>);
+  }
----------------
Nit: move this right under the definition of `FilterIteratorFor` (I think it would be easier to read when the definition and the usage are next to each other)?


================
Comment at: libcxx/test/std/ranges/range.adaptors/range.filter/iterator/deref.pass.cpp:35
+
+  std::array<int, 10> array{0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
+  FilterView view = make_filter_view(array.begin(), array.end(), AlwaysTrue{});
----------------
Very optional: any reason not to get CTAD to deduce the number of arguments? The element type seems obvious enough not to cause any issues.


================
Comment at: libcxx/test/std/ranges/range.adaptors/range.filter/iterator/increment.pass.cpp:140
+  tests();
+  // static_assert(tests());
+  return 0;
----------------
Looks like this is either a leftover, or some issue that requires a comment.


================
Comment at: libcxx/test/std/ranges/range.adaptors/range.filter/iterator/iter_move.pass.cpp:13
+// friend constexpr range_rvalue_reference_t<V> iter_move(iterator const& i)
+//  noexcept(noexcept(ranges::iter_move(i.current_)));
+
----------------
`noexcept` doesn't seem to be tested.


================
Comment at: libcxx/test/std/ranges/range.adaptors/range.filter/iterator/iter_move.pass.cpp:56
+
+int main(int, char**) {
+  tests();
----------------
Same comments as `iter_swap.pass.cpp`.


================
Comment at: libcxx/test/std/ranges/range.adaptors/range.filter/iterator/iter_swap.pass.cpp:14
+//  noexcept(noexcept(ranges::iter_swap(x.current_, y.current_)))
+//  requires(indirectly_swappable<iterator_t<V>>);
+
----------------
I don't see a test for this constraint. If you think it's overkill, feel free to ignore.


================
Comment at: libcxx/test/std/ranges/range.adaptors/range.filter/iterator/iter_swap.pass.cpp:36
+
+  auto make_filter_view = [](auto begin, auto end, auto pred) {
+    View view{Iterator(begin), Sentinel(Iterator(end))};
----------------
Optional: this function is duplicated in many of the test files, I wonder if it should be moved to `types.h`?


================
Comment at: libcxx/test/std/ranges/range.adaptors/range.filter/iterator/iter_swap.pass.cpp:50
+
+    assert(*it1 == 2 && *it2 == 4); // test the test
+    iter_swap(it1, it2);
----------------
Very optional: consider splitting this into two assertions (to make it easier to see which condition failed if debugging is ever necessary). Applies below as well.


================
Comment at: libcxx/test/std/ranges/range.adaptors/range.filter/iterator/iter_swap.pass.cpp:51
+    assert(*it1 == 2 && *it2 == 4); // test the test
+    iter_swap(it1, it2);
+    assert(*it1 == 4 && *it2 == 2);
----------------
I don't think this test file checks that `iter_swap` uses `ranges::iter_swap` (which a user can customize). Do you think it's worthwhile to test for that? Same with `iter_move`.


================
Comment at: libcxx/test/std/ranges/range.adaptors/range.filter/iterator/types.compile.pass.cpp:66
+
+  // Check iterator_category for various categories of ranges
+  {
----------------
Hmm, I don't see a test for
```
3.4 Otherwise, iterator_­category denotes C.
```

Would it be worthwhile to check with e.g. `random_access_iterator_tag`?


================
Comment at: libcxx/test/std/ranges/range.adaptors/range.filter/sentinel/base.pass.cpp:30
+    View view{Iterator(begin), Sentinel(Iterator(end))};
+    return FilterView(std::move(view), pred);
+  };
----------------
Ultranit: include `<utility>` (applies in a few test files).


================
Comment at: libcxx/test/std/ranges/range.adaptors/range.filter/sentinel/base.pass.cpp:37
+  FilterSentinel const sent = view.end();
+  std::same_as<Sentinel> auto result = sent.base();
+  assert(base(base(result)) == array.end());
----------------
Nit: should this (and other similar uses) be `decltype(auto)` in the light of our recent discussion?


================
Comment at: libcxx/test/std/ranges/range.adaptors/range.filter/sentinel/compare.pass.cpp:40
+  std::same_as<bool> auto result = (it == sent);
+  assert(!result);
+}
----------------
Optional: test the case where `result` is true as well?


================
Comment at: libcxx/test/std/ranges/range.adaptors/range.filter/sentinel/ctor.default.pass.cpp:12
+
+// filter_view<V>::<sentinel>() = default;
+
----------------
Optional: would it be worthwhile testing for noexcept-edness?


================
Comment at: libcxx/test/std/ranges/range.adaptors/range.filter/sentinel/ctor.parent.pass.cpp:12
+
+// constexpr explicit sentinel(filter_view&);
+
----------------
Optional: test that the constructor is `explicit`?


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D109086



More information about the libcxx-commits mailing list