[libcxx-commits] [PATCH] D101079: [libcxx][ranges] Add ranges::size CPO.
Louis Dionne via Phabricator via libcxx-commits
libcxx-commits at lists.llvm.org
Fri Apr 23 11:05:34 PDT 2021
ldionne requested changes to this revision.
ldionne added a comment.
This revision now requires changes to proceed.
Overall looks great, with a few comments.
Also:
1. Is there something to update in the Ranges progress document?
2. Can we add conformance tests for the types defined in libc++? `std::vector` & friends.
================
Comment at: libcxx/include/__ranges/size.h:9
+//===----------------------------------------------------------------------===//
+#ifndef _LIBCPP_RANGES_SIZE_H
+#define _LIBCPP_RANGES_SIZE_H
----------------
`_LIBCPP___RANGES_SIZE_H` if we want to be consistent? I agree it's ugly as hell though, so maybe we should revisit that policy! But for now let's be consistent?
================
Comment at: libcxx/include/__ranges/size.h:58
+concept __member_size = __size_enabled<_Tp> && requires(_Tp&& __t) {
+ { _VSTD::__decay_copy(_VSTD::forward<_Tp>(__t).size()) } -> integral;
+};
----------------
I think we need to introduce a proper concept for integer-like types:
```
template <typename _Ip>
concept __integer_like = !same_as<bool, _Ip> && integral<_Ip>;
```
According to the Standard:
> A type `I` other than `cv bool` is integer-like if it models `integral<I>` or if it is an integer-class type.
That would also be an indirection point where we can add our own implementation-defined integer-class type if we have one.
Right now, my understanding is that this concept would be satisfied if `t.size()` returned a `bool`. Instead, we should use `-> __integer_like` so that `bool` is excluded. Can you confirm that it's a problem and add a test that fails when that's the case?
This comment applies to other uses of `integral` below (and so we should add tests for those too).
================
Comment at: libcxx/include/__ranges/size.h:81-89
+ template <class _Tp, size_t _Sz>
+ [[nodiscard]] constexpr size_t operator()(_Tp (&&)[_Sz]) const noexcept {
+ return _Sz;
+ }
+
+ template <class _Tp, size_t _Sz>
+ [[nodiscard]] constexpr size_t operator()(_Tp (&)[_Sz]) const noexcept {
----------------
Just thinking out loud, but this works if you pass a reference to a const array because it'll deduce `_Tp = Foo const` such that the whole signature is `Foo const (&)[_Sz]`?
================
Comment at: libcxx/include/__ranges/size.h:106-107
+ noexcept(noexcept(ranges::end(__t) - ranges::begin(__t))) {
+ using _Unsigned = make_unsigned_t<range_difference_t<remove_cvref_t<_Tp>>>;
+ return static_cast<_Unsigned>(ranges::end(__t) - ranges::begin(__t));
+ }
----------------
Would it be worth creating a `__to_unsigned_like` helper function that we can reuse? I don't know the spec by heart, but I imagine that if they factored out the term of art to-unsigned-like in the spec (https://eel.is/c++draft/ranges#syn-1), it must be because we're re-using it elsewhere?
================
Comment at: libcxx/include/__ranges/size.h:110
+};
+}
+
----------------
`// end namespace __size`
================
Comment at: libcxx/include/__ranges/size.h:113
+inline namespace __cpo {
+inline constexpr const auto size = __size::__fn{};
+} // namespace __cpo
----------------
Indent inside the namespace!
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