@@ -46,6 +46,15 @@ concept cartesian_product_is_bidirectional =
4646 (bidirectional_range<__maybe_const<Const, First>> && ... &&
4747 (bidirectional_range<__maybe_const<Const, Vs>> && cartesian_product_common_arg<__maybe_const<Const, Vs>>));
4848
49+ template <class ... Vs>
50+ concept cartesian_product_is_sized = (sized_range<Vs> && ...);
51+
52+ template <bool Const, template <class > class FirstSent , class First , class ... Vs>
53+ concept cartesian_is_sized_sentinel =
54+ (sized_sentinel_for<FirstSent<__maybe_const<Const, First>>, iterator_t <__maybe_const<Const, First>>> && ... &&
55+ (sized_range<__maybe_const<Const, Vs>> &&
56+ sized_sentinel_for<iterator_t <__maybe_const<Const, Vs>>, iterator_t <__maybe_const<Const, Vs>>>));
57+
4958template <cartesian_product_common_arg R>
5059constexpr auto cartesian_common_arg_end (R& r) {
5160 if constexpr (common_range<R>) {
@@ -203,6 +212,12 @@ class cartesian_product_view<First, Vs...>::iterator {
203212 return iterator (x) -= y;
204213 }
205214
215+ friend constexpr iterator operator -(const iterator& x, const iterator& y)
216+ requires cartesian_product_is_random_access<Const, First, Vs...>
217+ {
218+ return x.distance_from (y.current_ );
219+ }
220+
206221private:
207222 using Parent = __maybe_const<Const, cartesian_product_view>;
208223 Parent* parent_ = nullptr ;
@@ -279,6 +294,27 @@ class cartesian_product_view<First, Vs...>::iterator {
279294 return at_end<N - 1 >();
280295 return false ;
281296 }
297+
298+ template <class Tuple >
299+ constexpr difference_type distance_from (const Tuple& t) const {
300+ constexpr auto seq = std::make_integer_sequence<int , sizeof ...(Vs) + 1 >{};
301+ constexpr auto scaled_sum = [&t, this ]<int ... Ints>(std::integer_sequence<int , Ints...>) -> difference_type {
302+ return (scaled_distance<Ints>(t) + ...);
303+ };
304+ return scaled_sum (seq);
305+ }
306+
307+ template <auto N>
308+ constexpr difference_type scaled_size () const {
309+ if constexpr (N <= sizeof ...(Vs))
310+ return static_cast <difference_type>(ranges::size (std::get<N>(parent_->bases_ ))) * scaled_size<N + 1 >();
311+ return static_cast <difference_type>(1 );
312+ }
313+
314+ template <auto N, class Tuple >
315+ constexpr difference_type scaled_distance (const Tuple& t) const {
316+ return static_cast <difference_type>(std::get<N>(current_) - std::get<N>(t)) * scaled_size<N + 1 >();
317+ }
282318};
283319
284320} // namespace ranges
0 commit comments