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

Arthur O'Dwyer via Phabricator via libcxx-commits libcxx-commits at lists.llvm.org
Thu Apr 22 10:49:27 PDT 2021


Quuxplusone added inline comments.


================
Comment at: libcxx/include/__ranges/size.h:86-90
+  template <__member_size _Tp>
+  [[nodiscard]] constexpr integral auto operator()(_Tp&& __t) const
+      noexcept(noexcept(_VSTD::forward<_Tp>(__t).size())) {
+    return _VSTD::forward<_Tp>(__t).size();
+  }
----------------
(A) I see how `integral auto` is mimicking https://eel.is/c++draft/range.prim.size#4 ; however, that seems to inappropriately restrict people from trying to use their own "integer-like" types, at the cost of compile-time-slowness and source-code-size. I propose that you remove the word `integral` from every overload here and below.

(B) Your `noexcept` specification fails to account for the decay-copy that happens if `__t.size()` returns `const SomeType&`. Admittedly, this is a problem //only// if you remove the `integral` constraint, because decay-copying a primitive integral type can't possibly throw.

(C) for the record: One might observe that all these conditional-noexcept-specifications violate the spirit of [P0884 "Extending the noexcept Policy"](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p0884r0.pdf) and propose removing them; but @tcanens has pointed out that "expression-equivalent to" implies "has the same noexceptness as," so we //are// actually mandated to use (correct) noexcept-specifications throughout basically all of Ranges. (Ugh, but unavoidable.)


================
Comment at: libcxx/include/__ranges/size.h:105
+
+  size_t operator()(auto &&) const = delete;
+};
----------------
Could you explain why this `=delete`'d overload is necessary?
I see how it is //observable// ( https://godbolt.org/z/PGxzf4jGz ) and I assume it is //permitted//, but I don't see why it's //necessary// in libc++. Other implementors (GCC, MSVC) get away without it.


================
Comment at: libcxx/include/__ranges/size.h:116
+
+#undef _LIBCPP_NOEXCEPT_RETURN
+
----------------
You can delete this line now. Thanks for removing this macro.


================
Comment at: libcxx/test/std/ranges/range.access/range.prim/size.compile.pass.cpp:122-123
+static_assert( std::is_invocable_v<RangeSizeT, InvalidReturnTypeFunction (&)[4]>);
+static_assert(!std::is_invocable_v<RangeSizeT, ConvertableReturnTypeMember>);
+static_assert(!std::is_invocable_v<RangeSizeT, ConvertableReturnTypeFunction>);
+
----------------
Throughout: s/Convertable/Convertible/


================
Comment at: libcxx/test/std/ranges/range.access/range.prim/size.compile.pass.cpp:126
+struct SizeMemberDisabled {
+  constexpr size_t size() { return 42; }
+};
----------------
(A) Remove `constexpr`. Remove the function body. `size_t size() const;` is sufficient.
(B) I notice you didn't const-qualify this member; I assume it was unintentional; but this is a good place to ask, what //is// supposed to happen if a type has a non-const-qualified `size()`? What does that imply for the truthiness of `sized_range<{const,} T{&,&&,}>`?


================
Comment at: libcxx/test/std/ranges/range.access/range.prim/size.compile.pass.cpp:192-196
+  IntPtrBeginAndEnd b;
+  assert(std::ranges::size(b) == 8);
+
+  DisabledSizeRangeWithBeginEnd c;
+  assert(std::ranges::size(c) == 8);
----------------
You use `assert` and have a `main`, but this file's name is `size.compile.pass.cpp`.
I suppose we need yet another CI step to prevent people from putting `main`s in their `.compile.pass.cpp` tests... and probably to prevent using the identifier-token `assert` in those files, either.


================
Comment at: libcxx/test/support/test_range.h:20
 struct sentinel {
-  bool operator==(std::input_or_output_iterator auto) const;
+  bool operator==(std::input_or_output_iterator auto) const { return true; }
 };
----------------
This function body should be unnecessary. If it's needed by some test, that test is wrong.
If for testing purposes we //want// a sentinel type that always produces an empty range, then we should name it something clearer than `struct sentinel`.


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