[libcxx-commits] [libcxx] [libc++][c++23] P2374: `views::cartesian_product` (PR #111215)
via libcxx-commits
libcxx-commits at lists.llvm.org
Sat Oct 5 15:11:47 PDT 2024
https://github.com/PaulXiCao updated https://github.com/llvm/llvm-project/pull/111215
>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 01/15] 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 02/15] 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 03/15] 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 04/15] 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 05/15] 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 06/15] 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 07/15] 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 08/15] 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;
>From 3cab3df41fd023b3c3608b61d90abb01dc575790 Mon Sep 17 00:00:00 2001
From: Paul <paulxicao7 at gmail.com>
Date: Sat, 5 Oct 2024 22:27:46 +0200
Subject: [PATCH 09/15] add to modulemap
---
libcxx/include/module.modulemap | 1 +
1 file changed, 1 insertion(+)
diff --git a/libcxx/include/module.modulemap b/libcxx/include/module.modulemap
index 881c0ca6c3669c..dc307c9c5600f8 100644
--- a/libcxx/include/module.modulemap
+++ b/libcxx/include/module.modulemap
@@ -1673,6 +1673,7 @@ module std [system] {
module access { header "__ranges/access.h" }
module all { header "__ranges/all.h" }
module as_rvalue_view { header "__ranges/as_rvalue_view.h" }
+ module cartesian_product_view { header "__ranges/cartesian_product_view.h" }
module chunk_by_view {
header "__ranges/chunk_by_view.h"
export std.functional.bind_back
>From db0a2be20d6126255732d07fd67c15b0571f13fa Mon Sep 17 00:00:00 2001
From: Paul <paulxicao7 at gmail.com>
Date: Sat, 5 Oct 2024 22:46:25 +0200
Subject: [PATCH 10/15] iterator: operator++(), next()
---
.../include/__ranges/cartesian_product_view.h | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
diff --git a/libcxx/include/__ranges/cartesian_product_view.h b/libcxx/include/__ranges/cartesian_product_view.h
index 16fe28a6122c92..7218da2906a8c1 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 <__iterator/access.h> // begin
#include <__memory/addressof.h>
#include <__ranges/concepts.h> // forward_range, view, range_size_t, sized_range, ...
#include <__ranges/zip_view.h> // tuple_transform
@@ -93,6 +94,11 @@ class cartesian_product_view<First, Vs...>::iterator {
return __tuple_transform([](auto& i) -> decltype(auto) { return *i; }, current_);
}
+ constexpr iterator& operator++() {
+ next();
+ return *this;
+ }
+
private:
using Parent = __maybe_const<Const, cartesian_product_view>;
Parent* parent_ = nullptr;
@@ -100,6 +106,18 @@ class cartesian_product_view<First, Vs...>::iterator {
constexpr iterator(Parent& parent, decltype(current_) current)
: parent_(std::addressof(parent)), current_(std::move(current)) {}
+
+ template <auto N = sizeof...(Vs)>
+ constexpr void next() {
+ const auto& v = std::get<N>(parent_->bases_);
+ auto& it = std::get<N>(current_);
+ if (++it == std::end(v)) {
+ if constexpr (N != 0) {
+ it = std::ranges::begin(v);
+ next<N - 1>();
+ }
+ }
+ }
};
} // namespace ranges
>From 1b5c94f914e40ea659dc51be6a328bf3eae40be0 Mon Sep 17 00:00:00 2001
From: Paul <paulxicao7 at gmail.com>
Date: Sat, 5 Oct 2024 23:05:50 +0200
Subject: [PATCH 11/15] iterator: operator++(int)
---
libcxx/include/__ranges/cartesian_product_view.h | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/libcxx/include/__ranges/cartesian_product_view.h b/libcxx/include/__ranges/cartesian_product_view.h
index 7218da2906a8c1..fd2d3f4e099804 100644
--- a/libcxx/include/__ranges/cartesian_product_view.h
+++ b/libcxx/include/__ranges/cartesian_product_view.h
@@ -99,6 +99,16 @@ class cartesian_product_view<First, Vs...>::iterator {
return *this;
}
+ constexpr void operator++(int) { next(); }
+
+ constexpr iterator operator++(int)
+ requires forward_range<__maybe_const<Const, First>>
+ {
+ auto tmp = *this;
+ next();
+ return tmp;
+ }
+
private:
using Parent = __maybe_const<Const, cartesian_product_view>;
Parent* parent_ = nullptr;
>From d11813e06a8eb6a288008c4fd1f9a96aaa5e5b4f Mon Sep 17 00:00:00 2001
From: Paul <paulxicao7 at gmail.com>
Date: Sat, 5 Oct 2024 23:38:28 +0200
Subject: [PATCH 12/15] iterator: operator--(), prev(); concepts
---
.../include/__ranges/cartesian_product_view.h | 40 +++++++++++++++++--
1 file changed, 37 insertions(+), 3 deletions(-)
diff --git a/libcxx/include/__ranges/cartesian_product_view.h b/libcxx/include/__ranges/cartesian_product_view.h
index fd2d3f4e099804..586dcde42c6f47 100644
--- a/libcxx/include/__ranges/cartesian_product_view.h
+++ b/libcxx/include/__ranges/cartesian_product_view.h
@@ -31,12 +31,27 @@ _LIBCPP_BEGIN_NAMESPACE_STD
namespace ranges {
+template <class R>
+concept cartesian_product_common_arg = common_range<R> || (sized_range<R> && random_access_range<R>);
+
+template <bool Const, class First, class... Vs>
+concept cartesian_product_is_bidirectional =
+ (bidirectional_range<__maybe_const<Const, First>> && ... &&
+ (bidirectional_range<__maybe_const<Const, Vs>> && cartesian_product_common_arg<__maybe_const<Const, Vs>>));
+
+template <cartesian_product_common_arg R>
+constexpr auto cartesian_common_arg_end(R& r) {
+ if constexpr (common_range<R>) {
+ return ranges::end(r);
+ } else {
+ return ranges::begin(r) + ranges::distance(r);
+ }
+}
+
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
+public: // fixme: make private
tuple<First, Vs...> bases_;
template <bool Const>
@@ -109,6 +124,13 @@ class cartesian_product_view<First, Vs...>::iterator {
return tmp;
}
+ constexpr iterator& operator--()
+ requires cartesian_product_is_bidirectional<Const, First, Vs...>
+ {
+ prev();
+ return *this;
+ }
+
private:
using Parent = __maybe_const<Const, cartesian_product_view>;
Parent* parent_ = nullptr;
@@ -128,6 +150,18 @@ class cartesian_product_view<First, Vs...>::iterator {
}
}
}
+
+ template <auto N = sizeof...(Vs)>
+ constexpr void prev() {
+ auto& it = std::get<N>(current_);
+ if constexpr (N > 0) {
+ if (const auto& v = std::get<N>(parent_->bases_); it == ranges::begin(v)) {
+ it = cartesian_common_arg_end(v);
+ prev<N - 1>();
+ }
+ }
+ --it;
+ }
};
} // namespace ranges
>From bf48c4963c1159bb703039251c5937d479b71905 Mon Sep 17 00:00:00 2001
From: Paul <paulxicao7 at gmail.com>
Date: Sat, 5 Oct 2024 23:41:32 +0200
Subject: [PATCH 13/15] iterator: next() as suggested in std
---
libcxx/include/__ranges/cartesian_product_view.h | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/libcxx/include/__ranges/cartesian_product_view.h b/libcxx/include/__ranges/cartesian_product_view.h
index 586dcde42c6f47..8fb4a09d4e8d22 100644
--- a/libcxx/include/__ranges/cartesian_product_view.h
+++ b/libcxx/include/__ranges/cartesian_product_view.h
@@ -141,11 +141,11 @@ class cartesian_product_view<First, Vs...>::iterator {
template <auto N = sizeof...(Vs)>
constexpr void next() {
- const auto& v = std::get<N>(parent_->bases_);
- auto& it = std::get<N>(current_);
- if (++it == std::end(v)) {
- if constexpr (N != 0) {
- it = std::ranges::begin(v);
+ auto& it = std::get<N>(current_);
+ ++it;
+ if constexpr (N > 0) {
+ if (const auto& v = std::get<N>(parent_->bases_); it == ranges::end(v)) {
+ it = ranges::begin(v);
next<N - 1>();
}
}
>From 5aed102f15ddaea2c4de813a81fb2fa102278b8b Mon Sep 17 00:00:00 2001
From: Paul <paulxicao7 at gmail.com>
Date: Sat, 5 Oct 2024 23:43:36 +0200
Subject: [PATCH 14/15] iterator: operator--(int)
---
libcxx/include/__ranges/cartesian_product_view.h | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/libcxx/include/__ranges/cartesian_product_view.h b/libcxx/include/__ranges/cartesian_product_view.h
index 8fb4a09d4e8d22..4f6fded8c74b3d 100644
--- a/libcxx/include/__ranges/cartesian_product_view.h
+++ b/libcxx/include/__ranges/cartesian_product_view.h
@@ -131,6 +131,13 @@ class cartesian_product_view<First, Vs...>::iterator {
return *this;
}
+ constexpr iterator operator--(int)
+requires cartesian_product_is_bidirectional <Const, First, Vs...> {
+ auto tmp = *this;
+ prev();
+ return tmp;
+}
+
private:
using Parent = __maybe_const<Const, cartesian_product_view>;
Parent* parent_ = nullptr;
>From e234275ce31d38127d4abae670725dc79bc182e5 Mon Sep 17 00:00:00 2001
From: Paul <paulxicao7 at gmail.com>
Date: Sun, 6 Oct 2024 00:11:27 +0200
Subject: [PATCH 15/15] iterator: operator+=(x), -=(x); concept
---
.../include/__ranges/cartesian_product_view.h | 58 ++++++++++++++++++-
1 file changed, 55 insertions(+), 3 deletions(-)
diff --git a/libcxx/include/__ranges/cartesian_product_view.h b/libcxx/include/__ranges/cartesian_product_view.h
index 4f6fded8c74b3d..495ec1fd63e51e 100644
--- a/libcxx/include/__ranges/cartesian_product_view.h
+++ b/libcxx/include/__ranges/cartesian_product_view.h
@@ -31,6 +31,11 @@ _LIBCPP_BEGIN_NAMESPACE_STD
namespace ranges {
+template <bool Const, class First, class... Vs>
+concept cartesian_product_is_random_access =
+ (random_access_range<__maybe_const<Const, First>> && ... &&
+ (random_access_range<__maybe_const<Const, Vs>> && sized_range<__maybe_const<Const, Vs>>));
+
template <class R>
concept cartesian_product_common_arg = common_range<R> || (sized_range<R> && random_access_range<R>);
@@ -97,6 +102,7 @@ class cartesian_product_view<First, Vs...>::iterator {
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>>...>;
+ using difference_type = std::common_type_t<range_difference_t<First>, range_difference_t<Vs>...>;
iterator() = default;
@@ -132,11 +138,26 @@ class cartesian_product_view<First, Vs...>::iterator {
}
constexpr iterator operator--(int)
-requires cartesian_product_is_bidirectional <Const, First, Vs...> {
- auto tmp = *this;
+ requires cartesian_product_is_bidirectional<Const, First, Vs...>
+ {
+ auto tmp = *this;
prev();
return tmp;
-}
+ }
+
+ constexpr iterator& operator+=(difference_type x)
+ requires cartesian_product_is_random_access<Const, First, Vs...>
+ {
+ advance(x);
+ return *this;
+ }
+
+ constexpr iterator& operator-=(difference_type x)
+ requires cartesian_product_is_random_access<Const, First, Vs...>
+ {
+ advance(x);
+ return *this;
+ }
private:
using Parent = __maybe_const<Const, cartesian_product_view>;
@@ -169,6 +190,37 @@ requires cartesian_product_is_bidirectional <Const, First, Vs...> {
}
--it;
}
+
+ template <std::size_t N = sizeof...(Vs)>
+ constexpr void advance(difference_type x) {
+ if (x == 0)
+ return;
+
+ const auto& v = std::get<N>(parent_->bases_);
+ auto& it = std::get<N>(current_);
+ const auto sz = static_cast<difference_type>(std::ranges::size(v));
+ const auto first = begin(v);
+
+ const auto idx = static_cast<difference_type>(it - first);
+ x += idx;
+
+ auto div = sz ? x / sz : 0;
+ auto mod = sz ? x % sz : 0;
+
+ if constexpr (N != 0) {
+ if (mod < 0) {
+ mod += sz;
+ div--;
+ }
+ advance<N - 1>(div);
+ } else {
+ if (div > 0) {
+ mod = sz;
+ }
+ }
+ using D = std::iter_difference_t<decltype(first)>;
+ it = first + static_cast<D>(mod);
+ }
};
} // namespace ranges
More information about the libcxx-commits
mailing list