[libcxx-commits] [libcxx] 6f1b10d - [libcxx][ranges] Add ranges::ssize CPO.
via libcxx-commits
libcxx-commits at lists.llvm.org
Tue May 4 21:54:03 PDT 2021
Author: zoecarver
Date: 2021-05-04T21:50:00-07:00
New Revision: 6f1b10df916f2d538dd56da2d9976169708d2ac3
URL: https://github.com/llvm/llvm-project/commit/6f1b10df916f2d538dd56da2d9976169708d2ac3
DIFF: https://github.com/llvm/llvm-project/commit/6f1b10df916f2d538dd56da2d9976169708d2ac3.diff
LOG: [libcxx][ranges] Add ranges::ssize CPO.
Based on D101079.
Differential Revision: https://reviews.llvm.org/D101189
Added:
libcxx/test/std/ranges/range.access/range.prim/ssize.pass.cpp
Modified:
libcxx/include/__ranges/size.h
libcxx/include/ranges
libcxx/test/std/ranges/range.access/range.prim/size.pass.cpp
Removed:
################################################################################
diff --git a/libcxx/include/__ranges/size.h b/libcxx/include/__ranges/size.h
index 74947bbc41fe..f2cfecfad3fc 100644
--- a/libcxx/include/__ranges/size.h
+++ b/libcxx/include/__ranges/size.h
@@ -98,6 +98,26 @@ namespace __size {
inline namespace __cpo {
inline constexpr auto size = __size::__fn{};
} // namespace __cpo
+
+namespace __ssize {
+ struct __fn {
+ template<class _Tp>
+ requires requires (_Tp&& __t) { ranges::size(__t); }
+ [[nodiscard]] constexpr integral auto operator()(_Tp&& __t) const
+ noexcept(noexcept(ranges::size(__t))) {
+ using _Signed = make_signed_t<decltype(ranges::size(__t))>;
+ if constexpr (sizeof(ptr
diff _t) > sizeof(_Signed))
+ return static_cast<ptr
diff _t>(ranges::size(__t));
+ else
+ return static_cast<_Signed>(ranges::size(__t));
+ }
+ };
+}
+
+inline namespace __cpo {
+ inline constexpr const auto ssize = __ssize::__fn{};
+} // namespace __cpo
+
} // namespace ranges
// clang-format off
diff --git a/libcxx/include/ranges b/libcxx/include/ranges
index 9062e34c4c97..c2b6bb306530 100644
--- a/libcxx/include/ranges
+++ b/libcxx/include/ranges
@@ -25,6 +25,7 @@ namespace std::ranges {
inline constexpr unspecified cend = unspecified;
inline constexpr unspecified size = unspecified;
+ inline constexpr unspecified ssize = unspecified;
}
// [range.range], ranges
diff --git a/libcxx/test/std/ranges/range.access/range.prim/size.pass.cpp b/libcxx/test/std/ranges/range.access/range.prim/size.pass.cpp
index 26da55cd7997..c5ff300811f1 100644
--- a/libcxx/test/std/ranges/range.access/range.prim/size.pass.cpp
+++ b/libcxx/test/std/ranges/range.access/range.prim/size.pass.cpp
@@ -9,7 +9,6 @@
// UNSUPPORTED: c++03, c++11, c++14, c++17
// UNSUPPORTED: libcpp-no-concepts
// UNSUPPORTED: gcc-10
-// XFAIL: msvc && clang
// std::ranges::size
@@ -51,9 +50,13 @@ bool constexpr testArrayType() {
SizeFunction d[4];
assert(std::ranges::size(a) == 4);
+ ASSERT_SAME_TYPE(decltype(std::ranges::size(a)), size_t);
assert(std::ranges::size(b) == 1);
+ ASSERT_SAME_TYPE(decltype(std::ranges::size(b)), size_t);
assert(std::ranges::size(c) == 4);
+ ASSERT_SAME_TYPE(decltype(std::ranges::size(c)), size_t);
assert(std::ranges::size(d) == 4);
+ ASSERT_SAME_TYPE(decltype(std::ranges::size(d)), size_t);
return true;
}
@@ -68,6 +71,7 @@ struct SizeMemberSigned {
bool constexpr testHasSizeMember() {
assert(std::ranges::size(SizeMember()) == 42);
+ ASSERT_SAME_TYPE(decltype(std::ranges::size(SizeMember())), size_t);
const SizeMemberConst sizeMemberConst;
assert(std::ranges::size(sizeMemberConst) == 42);
@@ -112,6 +116,7 @@ struct SizeFunctionSigned {
bool constexpr testHasSizeFunction() {
assert(std::ranges::size(SizeFunction()) == 42);
+ ASSERT_SAME_TYPE(decltype(std::ranges::size(SizeFunction())), size_t);
assert(std::ranges::size(MoveOnlySizeFunction()) == 42);
assert(std::ranges::size(EnumSizeFunction()) == 42);
assert(std::ranges::size(SizeFunctionConst()) == 42);
diff --git a/libcxx/test/std/ranges/range.access/range.prim/ssize.pass.cpp b/libcxx/test/std/ranges/range.access/range.prim/ssize.pass.cpp
new file mode 100644
index 000000000000..8b8878adef80
--- /dev/null
+++ b/libcxx/test/std/ranges/range.access/range.prim/ssize.pass.cpp
@@ -0,0 +1,95 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+// UNSUPPORTED: libcpp-no-concepts
+// UNSUPPORTED: gcc-10
+
+// std::ranges::ssize
+
+#include <ranges>
+
+#include <cassert>
+#include "test_macros.h"
+#include "test_iterators.h"
+
+using RangeSSizeT = decltype(std::ranges::ssize);
+
+static_assert(!std::is_invocable_v<RangeSSizeT, int[]>);
+static_assert( std::is_invocable_v<RangeSSizeT, int[1]>);
+static_assert( std::is_invocable_v<RangeSSizeT, int (&&)[1]>);
+static_assert( std::is_invocable_v<RangeSSizeT, int (&)[1]>);
+
+static_assert(std::semiregular<std::remove_cv_t<RangeSSizeT>>);
+
+struct SizeMember {
+ constexpr size_t size() { return 42; }
+};
+
+static_assert(!std::is_invocable_v<RangeSSizeT, const SizeMember>);
+
+struct SizeFunction {
+ friend constexpr size_t size(SizeFunction) { return 42; }
+};
+
+struct SizeFunctionSigned {
+ friend constexpr std::ptr
diff _t size(SizeFunctionSigned) { return 42; }
+};
+
+struct sentinel {
+ bool operator==(std::input_or_output_iterator auto) const { return true; }
+};
+
+struct RandomAccesslRange {
+ constexpr random_access_iterator<int*> begin() { return {}; }
+ constexpr sentinel end() { return {}; }
+};
+
+constexpr std::ptr
diff _t operator-(const sentinel, const random_access_iterator<int*>) { return 2; }
+constexpr std::ptr
diff _t operator-(const random_access_iterator<int*>, const sentinel) { return 2; }
+
+struct ShortUnsignedReturnType {
+ constexpr unsigned short size() { return 42; }
+};
+
+// size_t changes depending on the platform.
+using SignedSizeT = std::make_signed_t<size_t>;
+
+constexpr bool test() {
+ int a[4];
+
+ assert(std::ranges::ssize(a) == 4);
+ ASSERT_SAME_TYPE(decltype(std::ranges::ssize(a)), SignedSizeT);
+
+ assert(std::ranges::ssize(SizeMember()) == 42);
+ ASSERT_SAME_TYPE(decltype(std::ranges::ssize(SizeMember())), SignedSizeT);
+
+ assert(std::ranges::ssize(SizeFunction()) == 42);
+ ASSERT_SAME_TYPE(decltype(std::ranges::ssize(SizeFunction())), SignedSizeT);
+
+ assert(std::ranges::ssize(SizeFunctionSigned()) == 42);
+ ASSERT_SAME_TYPE(decltype(std::ranges::ssize(SizeFunctionSigned())), std::ptr
diff _t);
+
+ RandomAccesslRange b;
+ assert(std::ranges::ssize(b) == 2);
+ ASSERT_SAME_TYPE(decltype(std::ranges::ssize(b)), std::ptr
diff _t);
+
+ // This gets converted to ptr
diff _t because it's wider.
+ ShortUnsignedReturnType c;
+ assert(std::ranges::ssize(c) == 42);
+ ASSERT_SAME_TYPE(decltype(std::ranges::ssize(c)), ptr
diff _t);
+
+ return true;
+}
+
+int main(int, char**) {
+ test();
+ static_assert(test());
+
+ return 0;
+}
More information about the libcxx-commits
mailing list