15 #ifndef RANGES_V3_VIEW_CARTESIAN_PRODUCT_HPP
16 #define RANGES_V3_VIEW_CARTESIAN_PRODUCT_HPP
30 #include <range/v3/utility/static_const.hpp>
37 #include <range/v3/detail/prologue.hpp>
44 template<
typename State,
typename Value>
45 using product_cardinality = std::integral_constant<
47 State::value == 0 || Value::value == 0
48 ?
static_cast<cardinality
>(0)
49 : State::value == unknown || Value::value == unknown
51 : State::value == infinite || Value::value == infinite
53 : State::value == finite || Value::value == finite
55 :
static_cast<cardinality
>(
56 State::value * Value::value)>;
58 struct cartesian_size_fn
60 template(
typename Size,
typename Rng)(
61 requires integer_like_<Size> AND sized_range<Rng> AND
62 common_with<Size, range_size_t<Rng>>)
63 common_type_t<Size, range_size_t<Rng>> operator()(Size s, Rng && rng)
const
65 using S = common_type_t<Size, range_size_t<Rng>>;
66 return static_cast<S
>(s) *
static_cast<S
>(
ranges::size(rng));
70 template<
typename... Views>
71 using cartesian_product_cardinality =
73 std::integral_constant<cardinality, static_cast<cardinality>(
74 (
sizeof...(Views) > 0))>,
85 template<
typename...Views>
87 and_v<range<Views const>...>;
91 template(
typename IsConst,
typename... Views)(
92 concept (cartesian_produce_view_can_size_)(IsConst, Views...),
93 and_v<common_with<std::uintmax_t, range_size_t<meta::const_if<IsConst, Views>>>...>
97 template<
typename IsConst,
typename...Views>
99 and_v<sized_range<meta::const_if<IsConst, Views>>...> &&
100 CPP_concept_ref(ranges::cartesian_produce_view_can_size_, IsConst, Views...);
104 template(
typename IsConst,
typename... Views)(
105 concept (cartesian_produce_view_can_distance_)(IsConst, Views...),
112 template<
typename IsConst,
typename...Views>
115 CPP_concept_ref(ranges::cartesian_produce_view_can_distance_, IsConst, Views...);
119 template(
typename IsConst,
typename... Views)(
120 concept (cartesian_produce_view_can_random_)(IsConst, Views...),
121 and_v<random_access_iterator<iterator_t<meta::const_if<IsConst, Views>>>...>
125 template<
typename IsConst,
typename...Views>
128 CPP_concept_ref(ranges::cartesian_produce_view_can_random_, IsConst, Views...);
132 template(
typename IsConst,
typename... Views)(
133 concept (cartesian_produce_view_can_bidi_)(IsConst, Views...),
134 and_v<common_range<meta::const_if<IsConst, Views>>...,
135 bidirectional_iterator<iterator_t<meta::const_if<IsConst, Views>>>...>
139 template<
typename IsConst,
typename...Views>
142 CPP_concept_ref(ranges::cartesian_produce_view_can_bidi_, IsConst, Views...);
145 template<
typename... Views>
148 detail::cartesian_product_cardinality<Views...>::value>
152 CPP_assert(and_v<(forward_range<Views> && view_<Views>)...>);
153 CPP_assert(
sizeof...(Views) != 0);
155 static constexpr
auto my_cardinality =
156 detail::cartesian_product_cardinality<Views...>::value;
158 std::tuple<Views...> views_;
160 template<
bool IsConst_>
167 using constify_if = meta::const_if_c<IsConst_, T>;
168 using difference_type =
169 common_type_t<std::intmax_t, range_difference_t<Views>...>;
171 constify_if<cartesian_product_view> *
view_;
172 std::tuple<iterator_t<constify_if<Views>>...> its_;
176 auto & v = std::get<0>(
view_->views_);
177 auto & i = std::get<0>(its_);
178 auto const last = ranges::end(v);
179 RANGES_EXPECT(i != last);
182 template<std::
size_t N>
185 auto & v = std::get<N - 1>(
view_->views_);
186 auto & i = std::get<N - 1>(its_);
187 auto const last = ranges::end(v);
188 RANGES_EXPECT(i != last);
191 i = ranges::begin(v);
197 RANGES_EXPECT(
false);
199 template<std::
size_t N>
202 auto & v = std::get<N - 1>(
view_->views_);
203 auto & i = std::get<N - 1>(its_);
204 if(i == ranges::begin(v))
206 CPP_assert(cartesian_produce_view_can_bidi<IsConst, Views...>);
209 ranges::advance(i, ranges::end(v));
218 template<std::
size_t N>
221 return std::get<N - 1>(its_) == std::get<N - 1>(that.its_) &&
226 return difference_type{std::get<0>(that.its_) - std::get<0>(its_)};
228 template<std::
size_t N>
232 auto const scale = ranges::distance(std::get<N - 1>(
view_->views_));
233 auto const increment = std::get<N - 1>(that.its_) - std::get<N - 1>(its_);
234 return difference_type{d * scale + increment};
238 RANGES_EXPECT(
false);
240 RANGES_DIAGNOSTIC_PUSH
241 RANGES_DIAGNOSTIC_IGNORE_DIVIDE_BY_ZERO
242 template<std::
size_t N>
248 auto & i = std::get<N - 1>(its_);
249 auto const my_size =
static_cast<difference_type
>(
251 auto const first = ranges::begin(std::get<N - 1>(
view_->views_));
253 auto const idx =
static_cast<difference_type
>(i -
first);
254 RANGES_EXPECT(0 <= idx);
255 RANGES_EXPECT(idx < my_size || (N == 1 && idx == my_size && n < 0));
256 RANGES_EXPECT(n < INTMAX_MAX - idx);
259 auto n_div = n / my_size;
260 auto n_mod = n % my_size;
262 if(RANGES_CONSTEXPR_IF(N != 1))
271 RANGES_EXPECT(0 <= n_mod && n_mod < my_size);
273 if(RANGES_CONSTEXPR_IF(N == 1))
277 RANGES_EXPECT(n_div == 1);
278 RANGES_EXPECT(n_mod == 0);
283 RANGES_EXPECT(n_div == -1);
284 RANGES_EXPECT(n_mod == 0);
288 using D = iter_difference_t<decltype(
first)>;
289 i =
first +
static_cast<D
>(n_mod);
291 RANGES_DIAGNOSTIC_POP
295 ranges::advance(std::get<0>(its_),
296 ranges::end(std::get<0>(
view_->views_)));
298 template<std::
size_t N>
301 return check_at_end_(
303 at_end || bool(std::get<N - 1>(its_) ==
304 ranges::end(std::get<N - 1>(
view_->views_))));
306 cursor(
end_tag, constify_if<cartesian_product_view> * view,
312 std::get<0>(its_) = ranges::end(std::get<0>(view->views_));
314 cursor(
end_tag, constify_if<cartesian_product_view> * view,
319 CPP_assert(!common_range<View0> && random_access_range<View0> &&
321 std::get<0>(its_) += ranges::distance(std::get<0>(view->views_));
325 using value_type = std::tuple<range_value_t<Views>...>;
328 explicit cursor(
begin_tag, constify_if<cartesian_product_view> * view)
330 , its_(tuple_transform(view->views_, ranges::begin))
336 explicit cursor(
end_tag, constify_if<cartesian_product_view> * view)
340 common_range<meta::at_c<meta::list<constify_if<Views>...>, 0>>>{})
342 template(
bool Other)(
343 requires IsConst_ AND CPP_NOT(Other))
344 cursor(cursor<Other> that)
346 , its_(std::move(that.its_))
350 return tuple_transform(its_, detail::dereference_fn{});
358 return std::get<0>(its_) == ranges::end(std::get<0>(
view_->views_));
360 bool equal(cursor
const & that)
const
365 auto prev() -> CPP_ret(
void)(
371 auto CPP_fun(distance_to)(cursor
const & that)(
372 const requires cartesian_produce_view_can_distance<IsConst, Views...>)
374 return distance_(that,
meta::size_t<
sizeof...(Views)>{});
377 auto advance(difference_type n)
384 cursor<false> begin_cursor()
389 auto begin_cursor()
const
390 -> CPP_ret(cursor<true>)(
397 -> CPP_ret(cursor<false>)(
400 return cursor<false>{
end_tag{},
this};
403 auto end_cursor()
const
404 -> CPP_ret(cursor<true>)(
407 return cursor<true>{
end_tag{},
this};
410 auto end_cursor()
const
412 requires (!cartesian_produce_view_can_bidi<std::true_type, Views...>))
420 : views_{detail::move(views)...}
422 template(
typename...)(
423 requires (my_cardinality >= 0))
429 auto CPP_fun(size)()(
const
430 requires (my_cardinality < 0) &&
433 return tuple_foldl(views_, std::uintmax_t{1}, detail::cartesian_size_fn{});
436 auto CPP_fun(size)()(
437 requires (my_cardinality < 0) &&
440 return tuple_foldl(views_, std::uintmax_t{1}, detail::cartesian_size_fn{});
444 #if RANGES_CXX_DEDUCTION_GUIDES >= RANGES_CXX_DEDUCTION_GUIDES_17
445 template<
typename... Rng>
458 template(
typename... Rngs)(
459 requires (
sizeof...(Rngs) != 0) AND
460 concepts::and_v<(forward_range<Rngs> && viewable_range<Rngs>)...>)
465 all(
static_cast<Rngs &&
>(rngs))...};
467 #if defined(_MSC_VER)
468 template(
typename Rng0)(
469 requires forward_range<Rng0> AND viewable_range<Rng0>)
473 all(
static_cast<Rng0 &&
>(rng0))};
475 template(
typename Rng0,
typename Rng1)(
476 requires forward_range<Rng0> AND viewable_range<Rng0> AND
477 forward_range<Rng1> AND viewable_range<Rng1>)
479 operator()(Rng0 && rng0, Rng1 && rng1)
const
482 all(
static_cast<Rng0 &&
>(rng0)),
483 all(
static_cast<Rng1 &&
>(rng1))};
485 template(
typename Rng0,
typename Rng1,
typename Rng2)(
486 requires forward_range<Rng0> AND viewable_range<Rng0> AND
487 forward_range<Rng1> AND viewable_range<Rng1> AND
488 forward_range<Rng2> AND viewable_range<Rng2>)
490 operator()(Rng0 && rng0, Rng1 && rng1, Rng2 && rng2)
const
493 all(
static_cast<Rng0 &&
>(rng0)),
494 all(
static_cast<Rng1 &&
>(rng1)),
495 all(
static_cast<Rng2 &&
>(rng2))};
506 #include <range/v3/detail/epilogue.hpp>
CPP_concept sized_sentinel_for
\concept sized_sentinel_for
Definition: concepts.hpp:332
CPP_concept common_range
\concept common_range
Definition: concepts.hpp:180
CPP_concept view_
\concept view_
Definition: concepts.hpp:252
decltype(begin(declval(Rng &))) iterator_t
Definition: access.hpp:698
RANGES_INLINE_VARIABLE(detail::to_container_fn< detail::from_range< std::vector >>, to_vector) template< template< typename... > class ContT > auto to(RANGES_HIDDEN_DETAIL(detail
For initializing a container of the specified type with the elements of an Range.
Definition: conversion.hpp:399
CPP_concept cartesian_produce_view_can_const
\concept cartesian_produce_view_can_const
Definition: cartesian_product.hpp:86
CPP_concept cartesian_produce_view_can_bidi
\concept cartesian_produce_view_can_bidi
Definition: cartesian_product.hpp:140
CPP_concept cartesian_produce_view_can_size
\concept cartesian_produce_view_can_size
Definition: cartesian_product.hpp:98
CPP_concept cartesian_produce_view_can_random
\concept cartesian_produce_view_can_random
Definition: cartesian_product.hpp:126
CPP_concept cartesian_produce_view_can_distance
\concept cartesian_produce_view_can_distance
Definition: cartesian_product.hpp:113
std::integral_constant< bool, B > bool_
An integral constant wrapper for bool.
Definition: meta.hpp:168
std::integral_constant< std::size_t, N > size_t
An integral constant wrapper for std::size_t.
Definition: meta.hpp:163
_t< detail::at_< L, N > > at_c
Return the N th element in the meta::list L.
Definition: meta.hpp:1962
front< Pair > first
Retrieve the first element of the pair Pair.
Definition: meta.hpp:2251
meta::size_t< L::size()> size
An integral constant wrapper that is the size of the meta::list L.
Definition: meta.hpp:1696
Definition: range_fwd.hpp:488
Definition: cartesian_product.hpp:149
Definition: common_tuple.hpp:96
Definition: default_sentinel.hpp:26
Definition: range_fwd.hpp:490
A utility for constructing a view from a (derived) type that implements begin and end cursors.
Definition: facade.hpp:66
Definition: cartesian_product.hpp:453