diff --git a/libcxx/include/__ranges/cartesian_product_view.h b/libcxx/include/__ranges/cartesian_product_view.h index 8c09e2b097df9a..399c28585b1414 100644 --- a/libcxx/include/__ranges/cartesian_product_view.h +++ b/libcxx/include/__ranges/cartesian_product_view.h @@ -46,6 +46,15 @@ concept cartesian_product_is_bidirectional = (bidirectional_range<__maybe_const> && ... && (bidirectional_range<__maybe_const> && cartesian_product_common_arg<__maybe_const>)); +template +concept cartesian_product_is_sized = (sized_range && ...); + +template class FirstSent, class First, class... Vs> +concept cartesian_is_sized_sentinel = + (sized_sentinel_for>, iterator_t<__maybe_const>> && ... && + (sized_range<__maybe_const> && + sized_sentinel_for>, iterator_t<__maybe_const>>)); + template constexpr auto cartesian_common_arg_end(R& r) { if constexpr (common_range) { @@ -203,6 +212,12 @@ class cartesian_product_view::iterator { return iterator(x) -= y; } + friend constexpr iterator operator-(const iterator& x, const iterator& y) + requires cartesian_product_is_random_access + { + return x.distance_from(y.current_); + } + private: using Parent = __maybe_const; Parent* parent_ = nullptr; @@ -279,6 +294,27 @@ class cartesian_product_view::iterator { return at_end(); return false; } + + template + constexpr difference_type distance_from(const Tuple& t) const { + constexpr auto seq = std::make_integer_sequence{}; + constexpr auto scaled_sum = [&t, this](std::integer_sequence) -> difference_type { + return (scaled_distance(t) + ...); + }; + return scaled_sum(seq); + } + + template + constexpr difference_type scaled_size() const { + if constexpr (N <= sizeof...(Vs)) + return static_cast(ranges::size(std::get(parent_->bases_))) * scaled_size(); + return static_cast(1); + } + + template + constexpr difference_type scaled_distance(const Tuple& t) const { + return static_cast(std::get(current_) - std::get(t)) * scaled_size(); + } }; } // namespace ranges