[libcxx-commits] [libcxx] [libc++][c++23] P2374: `views::cartesian_product` (PR #111215)

via libcxx-commits libcxx-commits at lists.llvm.org
Fri Oct 4 14:46:53 PDT 2024


https://github.com/PaulXiCao created https://github.com/llvm/llvm-project/pull/111215

Closes #105209 .
WIP !!

>From b924fd473793394d8b8bd16e83f3acc5211937f4 Mon Sep 17 00:00:00 2001
From: Paul <paulxicao7 at gmail.com>
Date: Fri, 4 Oct 2024 19:04:39 +0200
Subject: [PATCH 1/8] wip

---
 libcxx/include/CMakeLists.txt                 |  1 +
 .../include/__ranges/cartesian_product_view.h | 95 +++++++++++++++++++
 libcxx/include/ranges                         |  1 +
 .../ctor.pass.cpp                             | 36 +++++++
 .../size.pass.cpp                             | 46 +++++++++
 5 files changed, 179 insertions(+)
 create mode 100644 libcxx/include/__ranges/cartesian_product_view.h
 create mode 100644 libcxx/test/std/ranges/range.adaptors/range.cartesian.product.view/ctor.pass.cpp
 create mode 100644 libcxx/test/std/ranges/range.adaptors/range.cartesian.product.view/size.pass.cpp

diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt
index 8a63280053340f..ae8dbcafd9ae61 100644
--- a/libcxx/include/CMakeLists.txt
+++ b/libcxx/include/CMakeLists.txt
@@ -647,6 +647,7 @@ set(files
   __ranges/access.h
   __ranges/all.h
   __ranges/as_rvalue_view.h
+  __ranges/cartesian_product_view.h
   __ranges/chunk_by_view.h
   __ranges/common_view.h
   __ranges/concepts.h
diff --git a/libcxx/include/__ranges/cartesian_product_view.h b/libcxx/include/__ranges/cartesian_product_view.h
new file mode 100644
index 00000000000000..46941b9e1c97dd
--- /dev/null
+++ b/libcxx/include/__ranges/cartesian_product_view.h
@@ -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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef _LIBCPP___RANGES_CARTESIAN_PRODUCT_VIEW_H
+#define _LIBCPP___RANGES_CARTESIAN_PRODUCT_VIEW_H
+
+#include <__config>
+#include <__ranges/concepts.h> // forward_range, view, range_size_t, sized_range, ...
+#include <tuple> // apply
+#include <type_traits> // common_type_t
+
+#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+#  pragma GCC system_header
+#endif
+
+_LIBCPP_PUSH_MACROS
+#include <__undef_macros>
+
+#if _LIBCPP_STD_VER >= 23
+
+_LIBCPP_BEGIN_NAMESPACE_STD
+
+namespace ranges {
+
+template <input_range First, forward_range... Vs>
+  requires(view<First> && ... && view<Vs>)
+class cartesian_product_view : public view_interface<cartesian_product_view<First, Vs...>> {
+private:
+  tuple<First, Vs...> bases_; // exposition only
+
+  template <bool Const>
+  struct iterator; // exposition only
+
+public:
+  constexpr cartesian_product_view() = default;
+  constexpr explicit cartesian_product_view(First first_base, Vs... bases)
+      : bases_{std::move(first_base), std::move(bases)...} {}
+
+  // constexpr iterator<false> begin()
+  //     requires (!simple-view<First> || ... || !simple-view<Vs>)
+  // {
+  //     return move_iterator(ranges::begin(bases_));
+  // }
+
+  // constexpr iterator<true> begin() const
+  //     requires (range<const First> && ... && range<const Vs>)
+  // {
+  //     return move_iterator(ranges::begin(__base_));
+  // }
+
+  // constexpr iterator<false> begin()
+  //   requires (!simple-view<First> || ... || !simple-view<Vs>);
+  // constexpr iterator<true> begin() const
+  //   requires (range<const First> && ... && range<const Vs>);
+
+  // constexpr iterator<false> end()
+  //   requires ((!simple-view<First> || ... || !simple-view<Vs>) &&
+  //     cartesian-product-is-common<First, Vs...>);
+  // constexpr iterator<true> end() const
+  //   requires cartesian-product-is-common<const First, const Vs...>;
+  // constexpr default_sentinel_t end() const noexcept;
+
+  // constexpr see below size()
+  //   requires cartesian-product-is-sized<First, Vs...>;
+  // constexpr see below size() const
+  // requires cartesian-product-is-sized<const First, const Vs...>;
+  constexpr auto size() const 
+    requires(sized_range<const First> && ... && sized_range<const Vs>)
+  {
+    return std::apply(
+        [](auto&&... bases) {
+          using size_type = std::common_type_t<std::ranges::range_size_t<decltype(bases)>...>;
+          return (static_cast<size_type>(std::ranges::size(bases)) * ...);
+        },
+        bases_);
+  }
+};
+
+template <class... Rs>
+cartesian_product_view(Rs&&...) -> cartesian_product_view<std::views::all_t<Rs>...>;
+
+} // namespace ranges
+
+_LIBCPP_END_NAMESPACE_STD
+
+#endif // _LIBCPP_STD_VER >= 23
+
+_LIBCPP_POP_MACROS
+
+#endif // _LIBCPP___RANGES_CARTESIAN_PRODUCT_VIEW_H
diff --git a/libcxx/include/ranges b/libcxx/include/ranges
index fa35874265de67..4d97b19f8f89f2 100644
--- a/libcxx/include/ranges
+++ b/libcxx/include/ranges
@@ -422,6 +422,7 @@ namespace std {
 
 #if _LIBCPP_STD_VER >= 23
 #  include <__ranges/as_rvalue_view.h>
+#  include <__ranges/cartesian_product_view.h>
 #  include <__ranges/chunk_by_view.h>
 #  include <__ranges/from_range.h>
 #  include <__ranges/repeat_view.h>
diff --git a/libcxx/test/std/ranges/range.adaptors/range.cartesian.product.view/ctor.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.cartesian.product.view/ctor.pass.cpp
new file mode 100644
index 00000000000000..72657095c792ef
--- /dev/null
+++ b/libcxx/test/std/ranges/range.adaptors/range.cartesian.product.view/ctor.pass.cpp
@@ -0,0 +1,36 @@
+//===----------------------------------------------------------------------===//
+//
+// 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, c++20
+
+// std::ranges::cartesian_product_view
+
+#include <cassert>
+#include <ranges>
+
+#include "test_iterators.h"
+
+struct DefaultConstructibleView : std::ranges::view_base {
+  int i_;
+  int* begin();
+  int* end();
+};
+
+constexpr bool test() {
+  { // view | views::as_rvalue
+    // DefaultConstructibleView v{{}, 3};
+    [[maybe_unused]] std::ranges::cartesian_product_view<DefaultConstructibleView> r1;
+    [[maybe_unused]] std::ranges::cartesian_product_view<DefaultConstructibleView, DefaultConstructibleView> r2;
+  }
+  return true;
+}
+
+int main() {
+  test();
+  static_assert(test());
+}
diff --git a/libcxx/test/std/ranges/range.adaptors/range.cartesian.product.view/size.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.cartesian.product.view/size.pass.cpp
new file mode 100644
index 00000000000000..5486f9416a66bf
--- /dev/null
+++ b/libcxx/test/std/ranges/range.adaptors/range.cartesian.product.view/size.pass.cpp
@@ -0,0 +1,46 @@
+//===----------------------------------------------------------------------===//
+//
+// 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, c++20
+
+// std::ranges::cartesian_product_view::size
+
+#include <cassert>
+#include <ranges>
+#include <initializer_list>
+
+constexpr bool test() {
+  {
+    using T = std::initializer_list<int>;
+
+    // example taken from: https://en.cppreference.com/w/cpp/ranges/cartesian_product_view/size
+    constexpr static T w = {1};
+    constexpr static T x = {2, 3};
+    constexpr static T y = {4, 5, 6};
+    constexpr static T z = {7, 8, 9, 10, 11, 12, 13};
+
+    constexpr  auto ww = std::ranges::views::all(w);
+    constexpr auto xx = std::ranges::views::all(x);
+    constexpr auto yy = std::ranges::views::all(y);
+    constexpr auto zz = std::ranges::views::all(z);
+
+    constexpr auto v = std::ranges::cartesian_product_view(ww, xx, yy, zz);
+    
+    assert(v.size() == 42);
+    assert(v.size() == w.size() * x.size() * y.size() * z.size());
+    static_assert(v.size() == 42);
+    static_assert(v.size() == w.size() * x.size() * y.size() * z.size());
+  }
+
+  return true;
+}
+
+int main() {
+  test();
+  static_assert(test());
+}

>From 5d09a65753e081b65638406f8be6b27f98fd769f Mon Sep 17 00:00:00 2001
From: Paul <paulxicao7 at gmail.com>
Date: Fri, 4 Oct 2024 20:31:41 +0200
Subject: [PATCH 2/8] non-const size()

---
 .../include/__ranges/cartesian_product_view.h | 21 ++++++++++++-------
 .../size.pass.cpp                             | 18 +++++++---------
 2 files changed, 21 insertions(+), 18 deletions(-)

diff --git a/libcxx/include/__ranges/cartesian_product_view.h b/libcxx/include/__ranges/cartesian_product_view.h
index 46941b9e1c97dd..59cf31e3503907 100644
--- a/libcxx/include/__ranges/cartesian_product_view.h
+++ b/libcxx/include/__ranges/cartesian_product_view.h
@@ -11,8 +11,8 @@
 
 #include <__config>
 #include <__ranges/concepts.h> // forward_range, view, range_size_t, sized_range, ...
-#include <tuple> // apply
-#include <type_traits> // common_type_t
+#include <tuple>               // apply
+#include <type_traits>         // common_type_t
 
 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
 #  pragma GCC system_header
@@ -65,13 +65,20 @@ class cartesian_product_view : public view_interface<cartesian_product_view<Firs
   //   requires cartesian-product-is-common<const First, const Vs...>;
   // constexpr default_sentinel_t end() const noexcept;
 
-  // constexpr see below size()
-  //   requires cartesian-product-is-sized<First, Vs...>;
-  // constexpr see below size() const
-  // requires cartesian-product-is-sized<const First, const Vs...>;
-  constexpr auto size() const 
+  constexpr auto size()
+    requires(sized_range<First> && ... && sized_range<Vs>)
+  {
+    return size_impl();
+  }
+
+  constexpr auto size() const
     requires(sized_range<const First> && ... && sized_range<const Vs>)
   {
+    return size_impl();
+  }
+
+private:
+  constexpr auto size_impl() const {
     return std::apply(
         [](auto&&... bases) {
           using size_type = std::common_type_t<std::ranges::range_size_t<decltype(bases)>...>;
diff --git a/libcxx/test/std/ranges/range.adaptors/range.cartesian.product.view/size.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.cartesian.product.view/size.pass.cpp
index 5486f9416a66bf..82ee47997f53b3 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.cartesian.product.view/size.pass.cpp
+++ b/libcxx/test/std/ranges/range.adaptors/range.cartesian.product.view/size.pass.cpp
@@ -15,26 +15,22 @@
 #include <initializer_list>
 
 constexpr bool test() {
-  {
-    using T = std::initializer_list<int>;
-
+  { // testing: constexpr auto size() const
     // example taken from: https://en.cppreference.com/w/cpp/ranges/cartesian_product_view/size
-    constexpr static T w = {1};
-    constexpr static T x = {2, 3};
-    constexpr static T y = {4, 5, 6};
-    constexpr static T z = {7, 8, 9, 10, 11, 12, 13};
+    constexpr static auto w = {1};
+    constexpr static auto x = {2, 3};
+    constexpr static auto y = {4, 5, 6};
+    constexpr static auto z = {7, 8, 9, 10, 11, 12, 13};
 
-    constexpr  auto ww = std::ranges::views::all(w);
+    constexpr auto ww = std::ranges::views::all(w);
     constexpr auto xx = std::ranges::views::all(x);
     constexpr auto yy = std::ranges::views::all(y);
     constexpr auto zz = std::ranges::views::all(z);
 
     constexpr auto v = std::ranges::cartesian_product_view(ww, xx, yy, zz);
-    
+
     assert(v.size() == 42);
     assert(v.size() == w.size() * x.size() * y.size() * z.size());
-    static_assert(v.size() == 42);
-    static_assert(v.size() == w.size() * x.size() * y.size() * z.size());
   }
 
   return true;

>From 3ffdc30e7f2672f182be03e151c5cd66e084c1df Mon Sep 17 00:00:00 2001
From: Paul <paulxicao7 at gmail.com>
Date: Fri, 4 Oct 2024 22:56:20 +0200
Subject: [PATCH 3/8] class cartesian_product_view<First, Vs...>::iterator:
 ctors

---
 .../include/__ranges/cartesian_product_view.h | 97 ++++++++++++++++++-
 1 file changed, 96 insertions(+), 1 deletion(-)

diff --git a/libcxx/include/__ranges/cartesian_product_view.h b/libcxx/include/__ranges/cartesian_product_view.h
index 59cf31e3503907..ac879120295047 100644
--- a/libcxx/include/__ranges/cartesian_product_view.h
+++ b/libcxx/include/__ranges/cartesian_product_view.h
@@ -13,6 +13,7 @@
 #include <__ranges/concepts.h> // forward_range, view, range_size_t, sized_range, ...
 #include <tuple>               // apply
 #include <type_traits>         // common_type_t
+#include <__type_traits/maybe_const.h>
 
 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
 #  pragma GCC system_header
@@ -31,10 +32,11 @@ template <input_range First, forward_range... Vs>
   requires(view<First> && ... && view<Vs>)
 class cartesian_product_view : public view_interface<cartesian_product_view<First, Vs...>> {
 private:
+public: // fixme: remove me
   tuple<First, Vs...> bases_; // exposition only
 
   template <bool Const>
-  struct iterator; // exposition only
+  class iterator; // exposition only
 
 public:
   constexpr cartesian_product_view() = default;
@@ -88,6 +90,99 @@ class cartesian_product_view : public view_interface<cartesian_product_view<Firs
   }
 };
 
+template<input_range First, forward_range... Vs>
+requires (view<First> && ... && view<Vs>)
+template<bool Const>
+class cartesian_product_view<First, Vs...>::iterator {
+
+  // fixme: implement properly. see section 5.2 in paper.
+  template <class... T>
+  using tuple_or_pair = tuple<T...>;
+
+public:
+//   using iterator_category = input_iterator_tag;
+//   using iterator_concept  = see below;
+//   using value_type = tuple-or-pair<range_value_t<__maybe_const<Const, First>>,
+//     range_value_t<__maybe_const<Const, Vs>>...>;
+//   using reference = tuple-or-pair<reference_t<__maybe_const<Const, First>>,
+//     reference_t<__maybe_const<Const, Vs>>...>;
+//   using difference_type = see below;
+
+  iterator() requires forward_range<__maybe_const<Const, First>> = default;
+
+  constexpr explicit iterator(tuple_or_pair<iterator_t<__maybe_const<Const, First>>,
+    iterator_t<__maybe_const<Const, Vs>>...> current) 
+      : current_(std::move(current)) {}
+
+  constexpr iterator(iterator<!Const> i) requires Const &&
+    (convertible_to<iterator_t<First>, iterator_t<__maybe_const<Const, First>>> &&
+      ... && convertible_to<iterator_t<Vs>, iterator_t<__maybe_const<Const, Vs>>>)
+      : current_(std::move(i.current_)) {}
+
+//   constexpr auto operator*() const;
+//   constexpr iterator& operator++();
+//   constexpr void operator++(int);
+//   constexpr iterator operator++(int) requires forward_range<__maybe_const<Const, First>>;
+
+//   constexpr iterator& operator--()
+//     requires cartesian-product-is-bidirectional<Const, First, Vs...>;
+//   constexpr iterator operator--(int)
+//     requires cartesian-product-is-bidirectional<Const, First, Vs...>;
+
+//   constexpr iterator& operator+=(difference_type x)
+//     requires cartesian-product-is-random-access<Const, First, Vs...>;
+//   constexpr iterator& operator-=(difference_type x)
+//     requires cartesian-product-is-random-access<Const, First, Vs...>;
+
+//   constexpr reference operator[](difference_type n) const
+//     requires cartesian-product-is-random-access<Const, First, Vs...>;
+
+//   friend constexpr bool operator==(const iterator& x, const iterator& y)
+//     requires equality_comparable<iterator_t<__maybe_const<Const, First>>>;
+
+//   friend constexpr bool operator==(const iterator& x, default_sentinel_t);
+
+//   friend constexpr auto operator<=>(const iterator& x, const iterator& y)
+//     requires all-random-access<Const, First, Vs...>;
+
+//   friend constexpr iterator operator+(const iterator& x, difference_type y)
+//     requires cartesian-product-is-random-access<Const, First, Vs...>;
+//   friend constexpr iterator operator+(difference_type x, const iterator& y)
+//     requires cartesian-product-is-random-access<Const, First, Vs...>;
+//   friend constexpr iterator operator-(const iterator& x, difference_type y)
+//     requires cartesian-product-is-random-access<Const, First, Vs...>;
+//   friend constexpr difference_type operator-(const iterator& x, const iterator& y)
+//     requires cartesian-is-sized-sentinel<Const, iterator_t, First, Vs...>;
+
+//   friend constexpr difference_type operator-(iterator i, default_sentinel_t)
+//     requires cartesian-is-sized-sentinel<Const, sentinel_t, First, Vs...>;
+//   friend constexpr difference_type operator-(default_sentinel_t, iterator i)
+//     requires cartesian-is-sized-sentinel<Const, sentinel_t, First, Vs...>;
+
+//   friend constexpr auto iter_move(const iterator& i) noexcept(see below);
+
+//   friend constexpr void iter_swap(const iterator& l, const iterator& r) noexcept(see below)
+//     requires (indirectly_swappable<iterator_t<__maybe_const<Const, First>>> && ... &&
+//       indirectly_swappable<iterator_t<__maybe_const<Const, Vs>>>);
+
+private:
+//   __maybe_const<Const, cartesian_product_view>* parent_ = nullptr; // exposition only
+  tuple_or_pair<iterator_t<__maybe_const<Const, First>>,
+    iterator_t<__maybe_const<Const, Vs>>...> current_; // exposition only
+
+//   template <size_t N = sizeof...(Vs)>
+//   constexpr void next(); // exposition only
+
+//   template <size_t N = sizeof...(Vs)>
+//   constexpr void prev(); // exposition only
+
+//   template <class Tuple>
+//   constexpr difference_type distance-from(Tuple t); // exposition only
+
+//   constexpr explicit iterator(tuple-or-pair<iterator_t<__maybe_const<Const, First>>,
+//     iterator_t<__maybe_const<Const, Vs>>...> current); // exposition only
+};
+
 template <class... Rs>
 cartesian_product_view(Rs&&...) -> cartesian_product_view<std::views::all_t<Rs>...>;
 

>From 7e80ce681d2393eaa43a94aa1bb02ba122ab7d86 Mon Sep 17 00:00:00 2001
From: Paul <paulxicao7 at gmail.com>
Date: Fri, 4 Oct 2024 23:16:15 +0200
Subject: [PATCH 4/8] cleanup

---
 .../include/__ranges/cartesian_product_view.h | 137 +++---------------
 1 file changed, 22 insertions(+), 115 deletions(-)

diff --git a/libcxx/include/__ranges/cartesian_product_view.h b/libcxx/include/__ranges/cartesian_product_view.h
index ac879120295047..811693f3749ce4 100644
--- a/libcxx/include/__ranges/cartesian_product_view.h
+++ b/libcxx/include/__ranges/cartesian_product_view.h
@@ -11,9 +11,9 @@
 
 #include <__config>
 #include <__ranges/concepts.h> // forward_range, view, range_size_t, sized_range, ...
-#include <tuple>               // apply
-#include <type_traits>         // common_type_t
 #include <__type_traits/maybe_const.h>
+#include <tuple>       // apply
+#include <type_traits> // common_type_t
 
 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
 #  pragma GCC system_header
@@ -32,41 +32,18 @@ template <input_range First, forward_range... Vs>
   requires(view<First> && ... && view<Vs>)
 class cartesian_product_view : public view_interface<cartesian_product_view<First, Vs...>> {
 private:
+
 public: // fixme: remove me
-  tuple<First, Vs...> bases_; // exposition only
+  tuple<First, Vs...> bases_;
 
   template <bool Const>
-  class iterator; // exposition only
+  class iterator;
 
 public:
   constexpr cartesian_product_view() = default;
   constexpr explicit cartesian_product_view(First first_base, Vs... bases)
       : bases_{std::move(first_base), std::move(bases)...} {}
 
-  // constexpr iterator<false> begin()
-  //     requires (!simple-view<First> || ... || !simple-view<Vs>)
-  // {
-  //     return move_iterator(ranges::begin(bases_));
-  // }
-
-  // constexpr iterator<true> begin() const
-  //     requires (range<const First> && ... && range<const Vs>)
-  // {
-  //     return move_iterator(ranges::begin(__base_));
-  // }
-
-  // constexpr iterator<false> begin()
-  //   requires (!simple-view<First> || ... || !simple-view<Vs>);
-  // constexpr iterator<true> begin() const
-  //   requires (range<const First> && ... && range<const Vs>);
-
-  // constexpr iterator<false> end()
-  //   requires ((!simple-view<First> || ... || !simple-view<Vs>) &&
-  //     cartesian-product-is-common<First, Vs...>);
-  // constexpr iterator<true> end() const
-  //   requires cartesian-product-is-common<const First, const Vs...>;
-  // constexpr default_sentinel_t end() const noexcept;
-
   constexpr auto size()
     requires(sized_range<First> && ... && sized_range<Vs>)
   {
@@ -90,102 +67,32 @@ class cartesian_product_view : public view_interface<cartesian_product_view<Firs
   }
 };
 
-template<input_range First, forward_range... Vs>
-requires (view<First> && ... && view<Vs>)
-template<bool Const>
-class cartesian_product_view<First, Vs...>::iterator {
-
-  // fixme: implement properly. see section 5.2 in paper.
-  template <class... T>
-  using tuple_or_pair = tuple<T...>;
+template <class... Vs>
+cartesian_product_view(Vs&&...) -> cartesian_product_view<views::all_t<Vs>...>;
 
+template <input_range First, forward_range... Vs>
+  requires(view<First> && ... && view<Vs>)
+template <bool Const>
+class cartesian_product_view<First, Vs...>::iterator {
 public:
-//   using iterator_category = input_iterator_tag;
-//   using iterator_concept  = see below;
-//   using value_type = tuple-or-pair<range_value_t<__maybe_const<Const, First>>,
-//     range_value_t<__maybe_const<Const, Vs>>...>;
-//   using reference = tuple-or-pair<reference_t<__maybe_const<Const, First>>,
-//     reference_t<__maybe_const<Const, Vs>>...>;
-//   using difference_type = see below;
-
-  iterator() requires forward_range<__maybe_const<Const, First>> = default;
-
-  constexpr explicit iterator(tuple_or_pair<iterator_t<__maybe_const<Const, First>>,
-    iterator_t<__maybe_const<Const, Vs>>...> current) 
+  iterator()
+    requires forward_range<__maybe_const<Const, First>>
+  = default;
+
+  constexpr explicit iterator(
+      tuple<iterator_t<__maybe_const<Const, First>>, iterator_t<__maybe_const<Const, Vs>>...> current)
       : current_(std::move(current)) {}
 
-  constexpr iterator(iterator<!Const> i) requires Const &&
-    (convertible_to<iterator_t<First>, iterator_t<__maybe_const<Const, First>>> &&
-      ... && convertible_to<iterator_t<Vs>, iterator_t<__maybe_const<Const, Vs>>>)
+  constexpr iterator(iterator<!Const> i)
+    requires Const && (convertible_to<iterator_t<First>, iterator_t<__maybe_const<Const, First>>> && ... &&
+                       convertible_to<iterator_t<Vs>, iterator_t<__maybe_const<Const, Vs>>>)
       : current_(std::move(i.current_)) {}
 
-//   constexpr auto operator*() const;
-//   constexpr iterator& operator++();
-//   constexpr void operator++(int);
-//   constexpr iterator operator++(int) requires forward_range<__maybe_const<Const, First>>;
-
-//   constexpr iterator& operator--()
-//     requires cartesian-product-is-bidirectional<Const, First, Vs...>;
-//   constexpr iterator operator--(int)
-//     requires cartesian-product-is-bidirectional<Const, First, Vs...>;
-
-//   constexpr iterator& operator+=(difference_type x)
-//     requires cartesian-product-is-random-access<Const, First, Vs...>;
-//   constexpr iterator& operator-=(difference_type x)
-//     requires cartesian-product-is-random-access<Const, First, Vs...>;
-
-//   constexpr reference operator[](difference_type n) const
-//     requires cartesian-product-is-random-access<Const, First, Vs...>;
-
-//   friend constexpr bool operator==(const iterator& x, const iterator& y)
-//     requires equality_comparable<iterator_t<__maybe_const<Const, First>>>;
-
-//   friend constexpr bool operator==(const iterator& x, default_sentinel_t);
-
-//   friend constexpr auto operator<=>(const iterator& x, const iterator& y)
-//     requires all-random-access<Const, First, Vs...>;
-
-//   friend constexpr iterator operator+(const iterator& x, difference_type y)
-//     requires cartesian-product-is-random-access<Const, First, Vs...>;
-//   friend constexpr iterator operator+(difference_type x, const iterator& y)
-//     requires cartesian-product-is-random-access<Const, First, Vs...>;
-//   friend constexpr iterator operator-(const iterator& x, difference_type y)
-//     requires cartesian-product-is-random-access<Const, First, Vs...>;
-//   friend constexpr difference_type operator-(const iterator& x, const iterator& y)
-//     requires cartesian-is-sized-sentinel<Const, iterator_t, First, Vs...>;
-
-//   friend constexpr difference_type operator-(iterator i, default_sentinel_t)
-//     requires cartesian-is-sized-sentinel<Const, sentinel_t, First, Vs...>;
-//   friend constexpr difference_type operator-(default_sentinel_t, iterator i)
-//     requires cartesian-is-sized-sentinel<Const, sentinel_t, First, Vs...>;
-
-//   friend constexpr auto iter_move(const iterator& i) noexcept(see below);
-
-//   friend constexpr void iter_swap(const iterator& l, const iterator& r) noexcept(see below)
-//     requires (indirectly_swappable<iterator_t<__maybe_const<Const, First>>> && ... &&
-//       indirectly_swappable<iterator_t<__maybe_const<Const, Vs>>>);
-
 private:
-//   __maybe_const<Const, cartesian_product_view>* parent_ = nullptr; // exposition only
-  tuple_or_pair<iterator_t<__maybe_const<Const, First>>,
-    iterator_t<__maybe_const<Const, Vs>>...> current_; // exposition only
-
-//   template <size_t N = sizeof...(Vs)>
-//   constexpr void next(); // exposition only
-
-//   template <size_t N = sizeof...(Vs)>
-//   constexpr void prev(); // exposition only
-
-//   template <class Tuple>
-//   constexpr difference_type distance-from(Tuple t); // exposition only
-
-//   constexpr explicit iterator(tuple-or-pair<iterator_t<__maybe_const<Const, First>>,
-//     iterator_t<__maybe_const<Const, Vs>>...> current); // exposition only
+  //   __maybe_const<Const, cartesian_product_view>* parent_ = nullptr;
+  tuple<iterator_t<__maybe_const<Const, First>>, iterator_t<__maybe_const<Const, Vs>>...> current_;
 };
 
-template <class... Rs>
-cartesian_product_view(Rs&&...) -> cartesian_product_view<std::views::all_t<Rs>...>;
-
 } // namespace ranges
 
 _LIBCPP_END_NAMESPACE_STD

>From f318b23f2d2cd86c4f052134a59e9ac9f77cc376 Mon Sep 17 00:00:00 2001
From: Paul <paulxicao7 at gmail.com>
Date: Fri, 4 Oct 2024 23:24:02 +0200
Subject: [PATCH 5/8] cartesian_product_view::iterator parent member

---
 .../include/__ranges/cartesian_product_view.h  | 18 +++++++-----------
 1 file changed, 7 insertions(+), 11 deletions(-)

diff --git a/libcxx/include/__ranges/cartesian_product_view.h b/libcxx/include/__ranges/cartesian_product_view.h
index 811693f3749ce4..bd0302f7f197d9 100644
--- a/libcxx/include/__ranges/cartesian_product_view.h
+++ b/libcxx/include/__ranges/cartesian_product_view.h
@@ -10,6 +10,7 @@
 #define _LIBCPP___RANGES_CARTESIAN_PRODUCT_VIEW_H
 
 #include <__config>
+#include <__memory/addressof.h>
 #include <__ranges/concepts.h> // forward_range, view, range_size_t, sized_range, ...
 #include <__type_traits/maybe_const.h>
 #include <tuple>       // apply
@@ -75,21 +76,16 @@ template <input_range First, forward_range... Vs>
 template <bool Const>
 class cartesian_product_view<First, Vs...>::iterator {
 public:
-  iterator()
-    requires forward_range<__maybe_const<Const, First>>
-  = default;
-
-  constexpr explicit iterator(
-      tuple<iterator_t<__maybe_const<Const, First>>, iterator_t<__maybe_const<Const, Vs>>...> current)
-      : current_(std::move(current)) {}
+  iterator() = default;
 
   constexpr iterator(iterator<!Const> i)
-    requires Const && (convertible_to<iterator_t<First>, iterator_t<__maybe_const<Const, First>>> && ... &&
-                       convertible_to<iterator_t<Vs>, iterator_t<__maybe_const<Const, Vs>>>)
-      : current_(std::move(i.current_)) {}
+    requires Const && (convertible_to<iterator_t<First>, iterator_t<const First>> && ... &&
+                       convertible_to<iterator_t<Vs>, iterator_t<const Vs>>)
+      : parent_(std::addressof(i.parent_)), current_(std::move(i.current_)) {}
 
 private:
-  //   __maybe_const<Const, cartesian_product_view>* parent_ = nullptr;
+  using Parent    = __maybe_const<Const, cartesian_product_view>;
+  Parent* parent_ = nullptr;
   tuple<iterator_t<__maybe_const<Const, First>>, iterator_t<__maybe_const<Const, Vs>>...> current_;
 };
 

>From 72ba4530d4333596782b235ac9d78937164a2e24 Mon Sep 17 00:00:00 2001
From: Paul <paulxicao7 at gmail.com>
Date: Fri, 4 Oct 2024 23:31:03 +0200
Subject: [PATCH 6/8] iterator: private ctor

---
 libcxx/include/__ranges/cartesian_product_view.h | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/libcxx/include/__ranges/cartesian_product_view.h b/libcxx/include/__ranges/cartesian_product_view.h
index bd0302f7f197d9..f330f186e72b83 100644
--- a/libcxx/include/__ranges/cartesian_product_view.h
+++ b/libcxx/include/__ranges/cartesian_product_view.h
@@ -87,6 +87,9 @@ class cartesian_product_view<First, Vs...>::iterator {
   using Parent    = __maybe_const<Const, cartesian_product_view>;
   Parent* parent_ = nullptr;
   tuple<iterator_t<__maybe_const<Const, First>>, iterator_t<__maybe_const<Const, Vs>>...> current_;
+
+  constexpr iterator(Parent& parent, decltype(current_) current)
+      : parent_(std::addressof(parent)), current_(std::move(current)) {}
 };
 
 } // namespace ranges

>From a9ff49b5796574f4a07e20eac7477d8042a93f75 Mon Sep 17 00:00:00 2001
From: Paul <paulxicao7 at gmail.com>
Date: Fri, 4 Oct 2024 23:34:55 +0200
Subject: [PATCH 7/8] iterator: tags

---
 libcxx/include/__ranges/cartesian_product_view.h | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/libcxx/include/__ranges/cartesian_product_view.h b/libcxx/include/__ranges/cartesian_product_view.h
index f330f186e72b83..65111a7f827426 100644
--- a/libcxx/include/__ranges/cartesian_product_view.h
+++ b/libcxx/include/__ranges/cartesian_product_view.h
@@ -76,6 +76,11 @@ template <input_range First, forward_range... Vs>
 template <bool Const>
 class cartesian_product_view<First, Vs...>::iterator {
 public:
+  using iterator_category = input_iterator_tag;
+  using value_type = tuple<range_value_t<__maybe_const<Const, First>>, range_value_t<__maybe_const<Const, Vs>>...>;
+  using reference =
+      tuple<range_reference_t<__maybe_const<Const, First>>, range_reference_t<__maybe_const<Const, Vs>>...>;
+
   iterator() = default;
 
   constexpr iterator(iterator<!Const> i)

>From a6b0981dbe86513309446575212e36b5f839d18f Mon Sep 17 00:00:00 2001
From: Paul <paulxicao7 at gmail.com>
Date: Fri, 4 Oct 2024 23:44:10 +0200
Subject: [PATCH 8/8] iterator: operator*()

---
 libcxx/include/__ranges/cartesian_product_view.h | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/libcxx/include/__ranges/cartesian_product_view.h b/libcxx/include/__ranges/cartesian_product_view.h
index 65111a7f827426..16fe28a6122c92 100644
--- a/libcxx/include/__ranges/cartesian_product_view.h
+++ b/libcxx/include/__ranges/cartesian_product_view.h
@@ -12,6 +12,7 @@
 #include <__config>
 #include <__memory/addressof.h>
 #include <__ranges/concepts.h> // forward_range, view, range_size_t, sized_range, ...
+#include <__ranges/zip_view.h> // tuple_transform
 #include <__type_traits/maybe_const.h>
 #include <tuple>       // apply
 #include <type_traits> // common_type_t
@@ -88,6 +89,10 @@ class cartesian_product_view<First, Vs...>::iterator {
                        convertible_to<iterator_t<Vs>, iterator_t<const Vs>>)
       : parent_(std::addressof(i.parent_)), current_(std::move(i.current_)) {}
 
+  constexpr auto operator*() const {
+    return __tuple_transform([](auto& i) -> decltype(auto) { return *i; }, current_);
+  }
+
 private:
   using Parent    = __maybe_const<Const, cartesian_product_view>;
   Parent* parent_ = nullptr;



More information about the libcxx-commits mailing list