[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