Skip to content

Commit 2026a50

Browse files
committed
view: end()
1 parent f13264a commit 2026a50

File tree

1 file changed

+39
-1
lines changed

1 file changed

+39
-1
lines changed

libcxx/include/__ranges/cartesian_product_view.h

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,20 @@ class cartesian_product_view : public view_interface<cartesian_product_view<Firs
9898
return iterator<true>(*this, __tuple_transform(ranges::begin, bases_));
9999
}
100100

101+
constexpr iterator<false> end()
102+
requires((!__simple_view<First> || ... || !__simple_view<Vs>) && cartesian_product_is_common<First, Vs...>)
103+
{
104+
constexpr bool is_const = false;
105+
return end_impl<is_const>();
106+
}
107+
108+
constexpr iterator<true> end() const
109+
requires(cartesian_product_is_common<const First, const Vs...>)
110+
{
111+
constexpr bool is_const = true;
112+
return end_impl<is_const>();
113+
}
114+
101115
constexpr auto size()
102116
requires(sized_range<First> && ... && sized_range<Vs>)
103117
{
@@ -111,6 +125,30 @@ class cartesian_product_view : public view_interface<cartesian_product_view<Firs
111125
}
112126

113127
private:
128+
template <bool is_const>
129+
constexpr iterator<is_const> end_impl() const {
130+
bool is_empty = end_is_empty();
131+
const auto ranges_to_iterators = [is_empty, &b = bases_]<std::size_t... I>(std::index_sequence<I...>) {
132+
const auto begin_or_first_end = [is_empty]<bool is_first>(const auto& rng) {
133+
if constexpr (is_first)
134+
return is_empty ? ranges::begin(rng) : cartesian_common_arg_end(rng);
135+
return ranges::begin(rng);
136+
};
137+
return std::make_tuple(begin_or_first_end<I == 0>(std::get<I>(b))...);
138+
};
139+
iterator<is_const> it(*this, ranges_to_iterators(std::make_index_sequence<1 + sizeof...(Vs)>{}));
140+
return it;
141+
}
142+
143+
template <auto N = 0>
144+
constexpr bool end_is_empty() const {
145+
if constexpr (N == sizeof...(Vs))
146+
return false;
147+
if (const auto& v = std::get<N + 1>(bases_); ranges::empty(v))
148+
return true;
149+
return end_is_empty<N + 1>();
150+
}
151+
114152
constexpr auto size_impl() const {
115153
return std::apply(
116154
[](auto&&... bases) {
@@ -332,7 +370,7 @@ class cartesian_product_view<First, Vs...>::iterator {
332370

333371
template <auto N = sizeof...(Vs)>
334372
constexpr bool at_end() const {
335-
if (std::get<N>(current_) == end(std::get<N>(parent_->bases_)))
373+
if (std::get<N>(current_) == ranges::end(std::get<N>(parent_->bases_)))
336374
return true;
337375
if constexpr (N > 0)
338376
return at_end<N - 1>();

0 commit comments

Comments
 (0)