[libcxx-commits] [PATCH] D115272: [libc++] [test] Refactor range.prim/empty.pass.cpp

Arthur O'Dwyer via Phabricator via libcxx-commits libcxx-commits at lists.llvm.org
Tue Dec 7 18:24:22 PST 2021


Quuxplusone marked 5 inline comments as done.
Quuxplusone added inline comments.


================
Comment at: libcxx/test/std/ranges/range.access/range.prim/empty.pass.cpp:122
 };
-static_assert(std::is_invocable_v<RangeSizeT, IntPtrBeginAndEnd&>);
 
----------------
var-const wrote:
> Question: why is it okay to remove this test?
`IntPtrBeginAndEnd` tests the case where `ranges::empty(e)` will do `ranges::size(e)`, so we look in `testUsingRangesSize()`... and hmm, indeed there's no test case in there for the plain old sized-sentinel case (merely test cases for member and ADL `size()` functions). I guess I should add back one of those.
(The counterargument is that we already have tests for all the different ways to enable `ranges::size(e)`... in `size.pass.cpp`. So repeating all those tests here is a little silly. But it's easy to add, so I'm just gonna do it. I'll call it `BeginEndSizedSentinel`.)


================
Comment at: libcxx/test/std/ranges/range.access/range.prim/empty.pass.cpp:125-126
   BeginEndAndEmpty e;
-  assert(std::ranges::empty(e) == true);
-
-  BeginEndAndConstEmpty f;
-  assert(std::ranges::empty(f) == true);
-  assert(std::ranges::empty(std::as_const(f)) == true);
+  assert(std::ranges::empty(e) == false);  // using begin()==end()
+  assert(std::ranges::empty(std::as_const(e)) == true);  // using empty()
 
----------------
These comments are backwards. Will fix.


================
Comment at: libcxx/test/std/ranges/range.access/range.prim/empty.pass.cpp:101
 struct BeginEndNotSizedSentinel {
-  friend constexpr forward_iterator<int*> begin(BeginEndNotSizedSentinel) { return {}; }
-  friend constexpr sentinel end(BeginEndNotSizedSentinel) { return {}; }
----------------
ldionne wrote:
> Was `forward_iterator` not relevant for test coverage? I guess we were only relying on the fact that it was not a `sized_range`?
Right — I take `BeginEndNotSizedSentinel` to mean "we're gonna call `begin() == end()`, and the sentinel is //not// a sized sentinel." (If it were sized, then `ranges::size` would be well-formed and thus we'd end up calling `ranges::size` instead of `begin() == end()`. So its being not-sized is important.)
If it's not sized //and// not a forward iterator, then we (that is, `ranges::empty`) can't even call `begin() == end()` because we don't want to invalidate its `begin()`.
I've now added a (passing) test case for "if the iterators are just input iterators, then `ranges::empty(e)` is ill-formed."


================
Comment at: libcxx/test/std/ranges/range.access/range.prim/empty.pass.cpp:106-114
-struct InvalidMinusBeginEnd {
-  friend constexpr random_access_iterator<int*> begin(InvalidMinusBeginEnd) { return {}; }
-  friend constexpr sentinel end(InvalidMinusBeginEnd) { return {}; }
-};
-
-// Int is integer-like, but it is not other_forward_iterator's difference_type.
-constexpr short operator-(sentinel, random_access_iterator<int*>) { return 2; }
----------------
ldionne wrote:
> I don't understand why this removal doesn't reduce test coverage.
On old line 114, we're verifying that `ranges::size(b)` would be ill-formed if we were to call it on old line 153. What actually happens on line 153 is that `ranges::empty(b)` calls `b.begin() == b.end()` to find out if the range is empty, because what we have here is not a sized sentinel — this is the same case tested with `BeginEndNotSizedSentinel` on new lines 118–119.


================
Comment at: libcxx/test/std/ranges/range.access/range.prim/empty.pass.cpp:142-146
-struct BeginEndAndConstEmpty {
-  int* begin();
-  int* end();
-  constexpr bool empty() const { return true; }
 };
----------------
ldionne wrote:
> How does this not reduce coverage? Now we don't test with a `empty() const` method anymore.
In that case we would expect `ranges::empty(x)` to call `x.empty()`, so you'll find that up in `testEmptyMember` (which hasn't changed much):
```
struct HasMemberAndFunction {
  constexpr bool empty() const { return true; }
  // We should never do ADL lookup for std::ranges::empty.
  friend bool empty(const HasMemberAndFunction&) { return false; }
};
~~~
  HasMemberAndFunction a;
  assert(std::ranges::empty(a) == true);
```


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D115272



More information about the libcxx-commits mailing list