[libcxx-commits] [PATCH] D101079: [libcxx][ranges] Add ranges::size CPO.

Arthur O'Dwyer via Phabricator via libcxx-commits libcxx-commits at lists.llvm.org
Tue May 4 09:33:45 PDT 2021


Quuxplusone added inline comments.


================
Comment at: libcxx/include/__iterator/concepts.h:142-145
+template<class _From>
+[[nodiscard]] constexpr auto __to_unsigned_like(_From __x) noexcept {
+  return static_cast<make_unsigned_t<_From>>(__x);
+}
----------------
It seems to me that this function belongs right below `make_unsigned_t`, and not right below `bidirectional_iterator`.


================
Comment at: libcxx/test/std/ranges/range.access/range.prim/size.pass.cpp:47
+
+bool constexpr testArrayType() {
+  int a[4];
----------------
`constexpr bool` (and likewise throughout)
https://quuxplusone.github.io/blog/2021/04/03/static-constexpr-whittling-knife/


================
Comment at: libcxx/test/std/ranges/range.access/range.prim/size.pass.cpp:172
+struct SizeMemberDisabled {
+  size_t size() { return 42; }
+};
----------------
`size_t size() const`


================
Comment at: libcxx/test/std/ranges/range.access/range.prim/size.pass.cpp:182-185
+// Intentionally disabling "const ConstSizeMemberDisabled". This doesn't disable anything
+// because T is always uncvrefed before being checked.
+template<>
+inline constexpr bool std::disable_sized_range<ConstSizeMemberDisabled> = true;
----------------
The comment doesn't match the code. I believe you intended to write
```
inline constexpr bool std::disable_sized_range<const ConstSizeMemberDisabled> = true;
```
Also, please rename to something like `s/ConstSizeMemberDisabled/ImproperlyDisabled/`


================
Comment at: libcxx/test/std/ranges/range.access/range.prim/size.pass.cpp:195
+struct ConstSizeFunctionDisabled {
+  friend size_t size(const ConstSizeFunctionDisabled) { return 42; }
+};
----------------
Pass-by-const-value alert!
Either add the `&`, or remove the `const`. (Personally I'd add the `&`.)
https://quuxplusone.github.io/blog/2019/01/03/const-is-a-contract/
That blog post ends with some `git grep` lines; please run them over this and the rest of your patches and see how many other typos they catch.


================
Comment at: libcxx/test/std/ranges/range.access/range.prim/size.pass.cpp:212-222
+struct sentinel {
+  bool operator==(std::input_or_output_iterator auto) const { return true; }
+};
+
+struct HasMinusBeginEnd {
+  friend constexpr forward_iterator<int*> begin(HasMinusBeginEnd) { return {}; }
+  friend constexpr sentinel end(HasMinusBeginEnd) { return {}; }
----------------
Do this instead:
```
struct HasMinusBeginEnd {
  struct sentinel {
    friend bool operator==(sentinel, forward_iterator<int*>);
    friend constexpr long operator-(sentinel, forward_iterator<int*>) { return 2; }
    friend long operator-(forward_iterator<int*>, sentinel);
  };
  friend constexpr forward_iterator<int*> begin(HasMinusBeginEnd) { return {}; }
  friend constexpr sentinel end(HasMinusBeginEnd) { return {}; }
};
```
This keeps everything nicely packaged together, and also indicates (by the presence of function bodies) which functions are actually called by the test, and even (by the presence of `constexpr`) which functions are constexpr-called by the test.

Similarly for the other tests.


================
Comment at: libcxx/test/std/ranges/range.access/range.prim/size.pass.cpp:231
+
+// Int is integer-like, but it is not other_forward_iterator's difference_type.
+constexpr short operator-(const sentinel, const other_forward_iterator) { return 2; }
----------------
Should this comment `s/Int/short/` or do I not understand it? What is capital-i `Int` in this context?


================
Comment at: libcxx/test/std/ranges/range.access/range.prim/size.pass.cpp:238
+
+struct RandomAccesslRange {
+  constexpr random_access_iterator<int*> begin() { return {}; }
----------------
Is the `l` meaningful?


================
Comment at: libcxx/test/std/ranges/range.access/range.prim/size.pass.cpp:252-260
+struct DisabledSizeRangeWithBeginEnd {
+  int buff[8];
+  constexpr int* begin() { return buff; }
+  constexpr int* end() { return buff + 8; }
+  constexpr size_t size() { return 1; }
+};
+
----------------
This is a good test. I'd like to see a similar one where `disable_sized_range` is //not// specialized; then my understanding is that `std::ranges::size(a)` would be supposed to return `a.size()` i.e. `1`, is that right?


================
Comment at: libcxx/test/std/ranges/range.access/range.prim/size.pass.cpp:266
+  // Ensure that this is converted to an *unsigned* type.
+  ASSERT_SAME_TYPE(decltype(std::ranges::size(a)), unsigned long);
+
----------------
This should be `std::make_unsigned_t<std::ptrdiff_t>`, I believe. I don't think we should assume `ptrdiff_t` is invariably `signed long`.
Ditto throughout.
Let's test against `long` (or `short` or whatever) only when it's possible for the reader to grep back and see where that `long` (or `short` or whatever) comes from.


Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D101079



More information about the libcxx-commits mailing list