[libcxx-commits] [libcxx] [libc++][ranges] LWG3715: `view_interface::empty` is overconstrained (PR #85004)

Xiaoyang Liu via libcxx-commits libcxx-commits at lists.llvm.org
Wed Mar 13 00:20:39 PDT 2024


https://github.com/xiaoyang-sde updated https://github.com/llvm/llvm-project/pull/85004

>From 7a0c2c5e77b7fb5f2bf3c543757d30685168d31f Mon Sep 17 00:00:00 2001
From: Xiaoyang Liu <siujoeng.lau at gmail.com>
Date: Tue, 12 Mar 2024 17:21:02 -0700
Subject: [PATCH 1/4] [libc++][ranges] implement LWG3715

---
 libcxx/docs/Status/Cxx23Issues.csv       |  2 +-
 libcxx/include/__ranges/view_interface.h | 16 ++++++++++++----
 2 files changed, 13 insertions(+), 5 deletions(-)

diff --git a/libcxx/docs/Status/Cxx23Issues.csv b/libcxx/docs/Status/Cxx23Issues.csv
index 70480b33820580..a0c5a284e3291c 100644
--- a/libcxx/docs/Status/Cxx23Issues.csv
+++ b/libcxx/docs/Status/Cxx23Issues.csv
@@ -181,7 +181,7 @@
 "`3711 <https://wg21.link/LWG3711>`__","Missing preconditions for slide_view constructor","July 2022","","","|ranges|"
 "`3712 <https://wg21.link/LWG3712>`__","``chunk_view`` and ``slide_view`` should not be ``default_initializable``","July 2022","","","|ranges|"
 "`3713 <https://wg21.link/LWG3713>`__","Sorted with respect to comparator (only)","July 2022","",""
-"`3715 <https://wg21.link/LWG3715>`__","``view_interface::empty`` is overconstrained","July 2022","","","|ranges|"
+"`3715 <https://wg21.link/LWG3715>`__","``view_interface::empty`` is overconstrained","July 2022","|Complete|","19.0","|ranges|"
 "`3719 <https://wg21.link/LWG3719>`__","Directory iterators should be usable with default sentinel","July 2022","|Complete|","17.0","|ranges|"
 "`3721 <https://wg21.link/LWG3721>`__","Allow an ``arg-id`` with a value of zero for ``width`` in ``std-format-spec``","July 2022","|Complete|","16.0","|format|"
 "`3724 <https://wg21.link/LWG3724>`__","``decay-copy`` should be constrained","July 2022","|Complete|","14.0"
diff --git a/libcxx/include/__ranges/view_interface.h b/libcxx/include/__ranges/view_interface.h
index 84dd1c316de379..ecc14c0a9471cb 100644
--- a/libcxx/include/__ranges/view_interface.h
+++ b/libcxx/include/__ranges/view_interface.h
@@ -51,16 +51,24 @@ class view_interface {
 public:
   template <class _D2 = _Derived>
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool empty()
-    requires forward_range<_D2>
+    requires sized_range<_D2> || forward_range<_D2>
   {
-    return ranges::begin(__derived()) == ranges::end(__derived());
+    if constexpr (sized_range<_D2>) {
+      return ranges::size(__derived()) == 0;
+    } else {
+      return ranges::begin(__derived()) == ranges::end(__derived());
+    }
   }
 
   template <class _D2 = _Derived>
   [[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool empty() const
-    requires forward_range<const _D2>
+    requires sized_range<const _D2> || forward_range<const _D2>
   {
-    return ranges::begin(__derived()) == ranges::end(__derived());
+    if constexpr (sized_range<const _D2>) {
+      return ranges::size(__derived()) == 0;
+    } else {
+      return ranges::begin(__derived()) == ranges::end(__derived());
+    }
   }
 
   template <class _D2 = _Derived>

>From 29e95e141f9fb3ece0bb09990e91b64e3e7e0426 Mon Sep 17 00:00:00 2001
From: Xiaoyang Liu <siujoeng.lau at gmail.com>
Date: Tue, 12 Mar 2024 17:21:52 -0700
Subject: [PATCH 2/4] [libc++][ranges] implement 'lwg3715.pass.cpp'

---
 .../view.interface/lwg3715.pass.cpp           | 31 +++++++++++++++++++
 1 file changed, 31 insertions(+)
 create mode 100644 libcxx/test/std/ranges/range.utility/view.interface/lwg3715.pass.cpp

diff --git a/libcxx/test/std/ranges/range.utility/view.interface/lwg3715.pass.cpp b/libcxx/test/std/ranges/range.utility/view.interface/lwg3715.pass.cpp
new file mode 100644
index 00000000000000..cc58f2facba012
--- /dev/null
+++ b/libcxx/test/std/ranges/range.utility/view.interface/lwg3715.pass.cpp
@@ -0,0 +1,31 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+
+// LWG 3715: `view_interface::empty` is overconstrained
+
+#include <cassert>
+#include <ranges>
+#include <sstream>
+
+bool test() {
+  std::istringstream input("1 2 3 4 5");
+  auto i = std::views::istream<int>(input);
+  auto r = std::views::counted(i.begin(), 4) | std::views::take(2);
+  static_assert(std::ranges::input_range<decltype(r)>);
+  static_assert(!std::ranges::forward_range<decltype(r)>);
+  static_assert(std::ranges::sized_range<decltype(r)>);
+  assert(!r.empty());
+  return true;
+}
+
+int main(int, char**) {
+  test();
+  return 0;
+}

>From a34519f04e80b88e2f4e9772050ef9a9d408c299 Mon Sep 17 00:00:00 2001
From: Xiaoyang Liu <siujoeng.lau at gmail.com>
Date: Wed, 13 Mar 2024 00:14:19 -0700
Subject: [PATCH 3/4] [libc++][ranges] remove 'lwg3715.pass.cpp'

---
 .../view.interface/lwg3715.pass.cpp           | 31 -------------------
 .../view.interface/view.interface.pass.cpp    | 11 +++++++
 2 files changed, 11 insertions(+), 31 deletions(-)
 delete mode 100644 libcxx/test/std/ranges/range.utility/view.interface/lwg3715.pass.cpp

diff --git a/libcxx/test/std/ranges/range.utility/view.interface/lwg3715.pass.cpp b/libcxx/test/std/ranges/range.utility/view.interface/lwg3715.pass.cpp
deleted file mode 100644
index cc58f2facba012..00000000000000
--- a/libcxx/test/std/ranges/range.utility/view.interface/lwg3715.pass.cpp
+++ /dev/null
@@ -1,31 +0,0 @@
-//===----------------------------------------------------------------------===//
-//
-// 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
-
-// LWG 3715: `view_interface::empty` is overconstrained
-
-#include <cassert>
-#include <ranges>
-#include <sstream>
-
-bool test() {
-  std::istringstream input("1 2 3 4 5");
-  auto i = std::views::istream<int>(input);
-  auto r = std::views::counted(i.begin(), 4) | std::views::take(2);
-  static_assert(std::ranges::input_range<decltype(r)>);
-  static_assert(!std::ranges::forward_range<decltype(r)>);
-  static_assert(std::ranges::sized_range<decltype(r)>);
-  assert(!r.empty());
-  return true;
-}
-
-int main(int, char**) {
-  test();
-  return 0;
-}
diff --git a/libcxx/test/std/ranges/range.utility/view.interface/view.interface.pass.cpp b/libcxx/test/std/ranges/range.utility/view.interface/view.interface.pass.cpp
index 2fc2fa8579996a..a996dcd49e9145 100644
--- a/libcxx/test/std/ranges/range.utility/view.interface/view.interface.pass.cpp
+++ b/libcxx/test/std/ranges/range.utility/view.interface/view.interface.pass.cpp
@@ -39,6 +39,14 @@ struct InputRange : std::ranges::view_interface<InputRange> {
   constexpr InputIter end() const { return InputIter(buff + 8); }
 };
 
+struct SizedInputRange : std::ranges::view_interface<SizedInputRange> {
+  int buff[8] = {0, 1, 2, 3, 4, 5, 6, 7};
+  constexpr InputIter begin() const { return InputIter(buff); }
+  constexpr sized_sentinel<InputIter> end() const { return sized_sentinel(InputIter(buff + 8)); }
+  constexpr std::size_t size() const { return 8; }
+};
+static_assert(std::ranges::sized_range<SizedInputRange>);
+
 struct NotSizedSentinel {
   using value_type = int;
   using difference_type = std::ptrdiff_t;
@@ -155,9 +163,12 @@ concept BoolOpInvocable = requires (T const& obj) { bool(obj); };
 
 constexpr bool testEmpty() {
   static_assert(!EmptyInvocable<InputRange>);
+  // LWG 3715: `view_interface::empty` is overconstrained
+  static_assert( EmptyInvocable<SizedInputRange>);
   static_assert( EmptyInvocable<ForwardRange>);
 
   static_assert(!BoolOpInvocable<InputRange>);
+  static_assert( BoolOpInvocable<SizedInputRange>);
   static_assert( BoolOpInvocable<ForwardRange>);
 
   ForwardRange forwardRange;

>From 56e2ee5c25b4abc6804c86a8a6b9701cafae925c Mon Sep 17 00:00:00 2001
From: Xiaoyang Liu <siujoeng.lau at gmail.com>
Date: Wed, 13 Mar 2024 00:20:25 -0700
Subject: [PATCH 4/4] [libc++][ranges] format code with 'clang-format'

---
 .../range.utility/view.interface/view.interface.pass.cpp      | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/libcxx/test/std/ranges/range.utility/view.interface/view.interface.pass.cpp b/libcxx/test/std/ranges/range.utility/view.interface/view.interface.pass.cpp
index a996dcd49e9145..6c7cda74a80522 100644
--- a/libcxx/test/std/ranges/range.utility/view.interface/view.interface.pass.cpp
+++ b/libcxx/test/std/ranges/range.utility/view.interface/view.interface.pass.cpp
@@ -164,11 +164,11 @@ concept BoolOpInvocable = requires (T const& obj) { bool(obj); };
 constexpr bool testEmpty() {
   static_assert(!EmptyInvocable<InputRange>);
   // LWG 3715: `view_interface::empty` is overconstrained
-  static_assert( EmptyInvocable<SizedInputRange>);
+  static_assert(EmptyInvocable<SizedInputRange>);
   static_assert( EmptyInvocable<ForwardRange>);
 
   static_assert(!BoolOpInvocable<InputRange>);
-  static_assert( BoolOpInvocable<SizedInputRange>);
+  static_assert(BoolOpInvocable<SizedInputRange>);
   static_assert( BoolOpInvocable<ForwardRange>);
 
   ForwardRange forwardRange;



More information about the libcxx-commits mailing list