[libcxx-commits] [libcxx] [libc++][ranges] LWG4001: `iota_view` should provide `empty` (PR #79687)

Hristo Hristov via libcxx-commits libcxx-commits at lists.llvm.org
Sat Jan 27 14:57:58 PST 2024


https://github.com/Zingam updated https://github.com/llvm/llvm-project/pull/79687

>From 87fe530b0a6afffb041f727ce261affc59d39d50 Mon Sep 17 00:00:00 2001
From: Zingam <zingam at outlook.com>
Date: Thu, 11 Jan 2024 10:04:20 +0200
Subject: [PATCH 1/2] [libc++][ranges] LWG4001: `iota_view` should provide
 `empty`

Implements: https://wg21.link/LWG4001
- https://eel.is/c++draft/range.iota.view
---
 libcxx/docs/Status/Cxx2cIssues.csv            |   2 +-
 libcxx/include/__ranges/iota_view.h           |   2 +
 .../range.iota.view/empty.pass.cpp            | 136 ++++++++++++++++++
 3 files changed, 139 insertions(+), 1 deletion(-)
 create mode 100644 libcxx/test/std/ranges/range.factories/range.iota.view/empty.pass.cpp

diff --git a/libcxx/docs/Status/Cxx2cIssues.csv b/libcxx/docs/Status/Cxx2cIssues.csv
index b69b0948325412d..6401c7c6d8fc7d2 100644
--- a/libcxx/docs/Status/Cxx2cIssues.csv
+++ b/libcxx/docs/Status/Cxx2cIssues.csv
@@ -38,7 +38,7 @@
 "`3974 <https://wg21.link/LWG3974>`__","``mdspan::operator[]`` should not copy ``OtherIndexTypes``","Kona November 2023","","",""
 "`3987 <https://wg21.link/LWG3987>`__","Including ``<flat_foo>`` doesn't provide ``std::begin``/``end``","Kona November 2023","","","|flat_containers|"
 "`3990 <https://wg21.link/LWG3990>`__","Program-defined specializations of ``std::tuple`` and ``std::variant`` can't be properly supported","Kona November 2023","","",""
-"`4001 <https://wg21.link/LWG4001>`__","``iota_view`` should provide ``empty``","Kona November 2023","","","|ranges|"
+"`4001 <https://wg21.link/LWG4001>`__","``iota_view`` should provide ``empty``","Kona November 2023","|Complete|","19.0","|ranges|"
 "","","","","",""
 "`3343 <https://wg21.link/LWG3343>`__","Ordering of calls to ``unlock()`` and ``notify_all()`` in Effects element of ``notify_all_at_thread_exit()`` should be reversed","Not Yet Adopted","|Complete|","16.0",""
 "","","","","",""
diff --git a/libcxx/include/__ranges/iota_view.h b/libcxx/include/__ranges/iota_view.h
index c8314dd848b4473..6c5923c7ef013c2 100644
--- a/libcxx/include/__ranges/iota_view.h
+++ b/libcxx/include/__ranges/iota_view.h
@@ -345,6 +345,8 @@ class iota_view : public view_interface<iota_view<_Start, _BoundSentinel>> {
     return __iterator{__bound_sentinel_};
   }
 
+  _LIBCPP_HIDE_FROM_ABI constexpr bool empty() const { return __value_ == __bound_sentinel_; }
+
   _LIBCPP_HIDE_FROM_ABI constexpr auto size() const
     requires(same_as<_Start, _BoundSentinel> && __advanceable<_Start>) ||
             (integral<_Start> && integral<_BoundSentinel>) || sized_sentinel_for<_BoundSentinel, _Start>
diff --git a/libcxx/test/std/ranges/range.factories/range.iota.view/empty.pass.cpp b/libcxx/test/std/ranges/range.factories/range.iota.view/empty.pass.cpp
new file mode 100644
index 000000000000000..e7adffaf63b4c91
--- /dev/null
+++ b/libcxx/test/std/ranges/range.factories/range.iota.view/empty.pass.cpp
@@ -0,0 +1,136 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+
+// constexpr bool empty() const;
+
+#include <cassert>
+#include <concepts>
+#include <ranges>
+#include <utility>
+#include <vector>
+
+#include "types.h"
+
+template <typename R>
+concept HasFreeEmpty = requires(R r) { std::ranges::empty(r); };
+
+template <typename R>
+concept HasMemberEmpty = requires(R r) {
+  { r.empty() } -> std::same_as<bool>;
+};
+
+constexpr void test_empty_iota() {
+  std::vector<int> ev;
+
+  // Both parameters are non-const
+  {
+    auto iv = std::views::iota(std::ranges::begin(ev), std::ranges::end(ev));
+
+    static_assert(HasFreeEmpty<decltype(iv)>);
+    static_assert(HasMemberEmpty<decltype(iv)>);
+
+    assert(iv.empty());
+  }
+  // Left paramter is const
+  {
+    auto iv = std::views::iota(std::ranges::begin(std::as_const(ev)), std::ranges::end(ev));
+
+    static_assert(HasFreeEmpty<decltype(iv)>);
+    static_assert(HasMemberEmpty<decltype(iv)>);
+
+    assert(iv.empty());
+  }
+  // Right paramter is const
+  {
+    auto iv = std::views::iota(std::ranges::begin(ev), std::ranges::end(std::as_const(ev)));
+
+    static_assert(HasFreeEmpty<decltype(iv)>);
+    static_assert(HasMemberEmpty<decltype(iv)>);
+
+    assert(iv.empty());
+  }
+  // Both parameters are const
+  {
+    auto iv = std::views::iota(std::ranges::begin(std::as_const(ev)), std::ranges::end(std::as_const(ev)));
+
+    static_assert(HasFreeEmpty<decltype(iv)>);
+    static_assert(HasMemberEmpty<decltype(iv)>);
+
+    assert(iv.empty());
+  }
+
+  std::vector<char> v{'b', 'a', 'b', 'a', 'z', 'm', 't'};
+  auto fv = v | std::views::filter([](auto val) { return val == '0'; });
+
+  {
+    auto iv = std::views::iota(std::ranges::begin(fv), std::ranges::end(fv));
+
+    static_assert(HasFreeEmpty<decltype(iv)>);
+    static_assert(HasMemberEmpty<decltype(iv)>);
+
+    assert(iv.empty());
+  }
+}
+
+constexpr void test_nonempty_iota() {
+  // Default ctr
+  {
+    std::ranges::iota_view<Int42<DefaultTo42>> iv;
+
+    static_assert(HasFreeEmpty<decltype(iv)>);
+    static_assert(HasMemberEmpty<decltype(iv)>);
+
+    assert(!iv.empty());
+  }
+  // Value pass
+  {
+    std::ranges::iota_view<SomeInt> iv(SomeInt(94));
+
+    static_assert(HasFreeEmpty<decltype(iv)>);
+    static_assert(HasMemberEmpty<decltype(iv)>);
+
+    assert(!iv.empty());
+  }
+
+  {
+    std::vector<char> v;
+    auto it = std::back_inserter(v);
+    auto iv = std::views::iota(it);
+
+    static_assert(HasFreeEmpty<decltype(iv)>);
+    static_assert(HasMemberEmpty<decltype(iv)>);
+
+    assert(!iv.empty());
+  }
+  {
+    std::vector<char> v{'b', 'a', 'b', 'a', 'z', 'm', 't'};
+    auto it = std::back_inserter(v);
+    auto iv = std::views::iota(it);
+
+    static_assert(HasFreeEmpty<decltype(iv)>);
+    static_assert(HasMemberEmpty<decltype(iv)>);
+
+    assert(!iv.empty());
+  }
+}
+
+constexpr bool test() {
+  test_empty_iota();
+  test_nonempty_iota();
+
+  return true;
+}
+
+int main(int, char**) {
+  test();
+  static_assert(test());
+
+  return 0;
+}

>From 550a505f37c23c90bd10a0802ab0144d4e57ed70 Mon Sep 17 00:00:00 2001
From: Hristo Hristov <zingam at outlook.com>
Date: Sun, 28 Jan 2024 00:57:51 +0200
Subject: [PATCH 2/2] Update
 libcxx/test/std/ranges/range.factories/range.iota.view/empty.pass.cpp

Co-authored-by: Will Hawkins <whh8b at obs.cr>
---
 .../std/ranges/range.factories/range.iota.view/empty.pass.cpp   | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libcxx/test/std/ranges/range.factories/range.iota.view/empty.pass.cpp b/libcxx/test/std/ranges/range.factories/range.iota.view/empty.pass.cpp
index e7adffaf63b4c91..28af27297cbd88a 100644
--- a/libcxx/test/std/ranges/range.factories/range.iota.view/empty.pass.cpp
+++ b/libcxx/test/std/ranges/range.factories/range.iota.view/empty.pass.cpp
@@ -38,7 +38,7 @@ constexpr void test_empty_iota() {
 
     assert(iv.empty());
   }
-  // Left paramter is const
+  // Left parameter is const
   {
     auto iv = std::views::iota(std::ranges::begin(std::as_const(ev)), std::ranges::end(ev));
 



More information about the libcxx-commits mailing list