5 #ifndef VCCC_RANGES_VIEWS_CARTESIAN_PRODUCT_VIEW_HPP
6 #define VCCC_RANGES_VIEWS_CARTESIAN_PRODUCT_VIEW_HPP
46 template<
bool Const,
typename First,
typename... Vs>
47 struct cartesian_product_is_random_access
49 random_access_range<maybe_const<Const, First>>,
50 random_access_range<maybe_const<Const, Vs>>...,
51 sized_range<maybe_const<Const, Vs>>...
55 struct cartesian_product_common_arg
58 conjunction< sized_range<R>, random_access_range<R> >
61 template<
bool Const,
typename First,
typename... Vs>
62 struct cartesian_product_is_bidirectional
64 bidirectional_range<maybe_const<Const, First>>,
65 bidirectional_range<maybe_const<Const, Vs>>...,
66 cartesian_product_common_arg<maybe_const<Const, Vs>>...
69 template<
typename First,
typename... Vs>
70 struct cartesian_product_is_common : cartesian_product_common_arg<First> {};
72 template<
typename... Vs>
73 struct cartesian_product_is_sized : conjunction<sized_range<Vs>...> {};
75 template<
bool Const,
template<
typename>
class FirstSent,
typename First,
typename... Vs>
76 struct cartesian_is_sized_sentinel
79 FirstSent<maybe_const<Const, First>>,
80 iterator_t<maybe_const<Const, First>>>,
81 sized_range<maybe_const<Const, Vs>>...,
83 iterator_t<maybe_const<Const, Vs>>,
84 iterator_t<maybe_const<Const, Vs>>>...
88 constexpr
auto cartesian_common_arg_end_impl(R& r, std::true_type ) {
92 constexpr
auto cartesian_common_arg_end_impl(R& r, std::false_type ) {
97 constexpr
auto cartesian_common_arg_end(R& r) {
98 return vccc::ranges::detail::cartesian_common_arg_end_impl(r, common_range<R>{});
101 template<
typename R,
typename F,
typename Tuple, std::size_t... I>
102 constexpr R cartesian_tuple_transform_impl(F func, Tuple&& t, std::index_sequence<I...>)
105 noexcept(func(std::get<I>( std::forward<Tuple>(t) )))
109 return R(func(std::get<I>( std::forward<Tuple>(t) ))...);
112 template<
typename R,
typename F,
typename Tuple>
113 constexpr R cartesian_tuple_transform(F func, Tuple&& t)
115 cartesian_tuple_transform_impl<R>(
117 std::forward<Tuple>(t),
118 std::make_index_sequence<std::tuple_size<remove_cvref_t<Tuple>>::
value>{})
121 return cartesian_tuple_transform_impl<R>(
123 std::forward<Tuple>(t),
124 std::make_index_sequence<std::tuple_size<remove_cvref_t<Tuple>>::
value>{});
127 template<
typename F,
typename Tuple, std::size_t... I>
128 constexpr
auto cartesian_tuple_transform_impl(F func, Tuple&& t, std::index_sequence<I...>) {
129 return std::make_tuple(
131 std::get<I>( std::forward<Tuple>(t) )
136 template<
typename F,
typename Tuple>
137 constexpr
auto cartesian_tuple_transform(F func, Tuple&& t) {
138 return cartesian_tuple_transform_impl(
140 std::forward<Tuple>(t),
141 std::make_index_sequence<std::tuple_size<remove_cvref_t<Tuple>>::
value>{});
144 template<
typename Tuple,
typename Indices>
145 struct cartesian_product_is_empty_impl;
147 template<
typename Tuple, std::size_t... I>
148 struct cartesian_product_is_empty_impl<Tuple,
std::index_sequence<0, I...>>
154 struct cartesian_product_is_empty : cartesian_product_is_empty_impl<Tuple, std::make_index_sequence<N>> {};
156 template<
typename Tuple>
struct cartesian_product_is_empty<Tuple, 1> : std::false_type {};
157 template<
typename Tuple>
struct cartesian_product_is_empty<Tuple, 0>;
159 template<
typename F,
typename Tuple, std::size_t... I>
160 constexpr
auto cartesian_tuple_transform_end(F func,
const Tuple& t, std::index_sequence<0, I...>) {
161 return std::make_tuple(func(std::get<I>(t))...);
169 template<
typename First,
typename... Vs>
171 std::tuple<First, Vs...> bases_;
173 using iterator_current = std::tuple<
183 template<
bool Const>
class iterator;
209 #if __cplusplus < 202002L
215 template<
bool AntiConst, std::enable_if_t<
conjunction<
221 : parent_(i.parent_), current_(
std::move(i.current_)) {}
224 return detail::cartesian_tuple_transform(
225 [](
auto& i) -> decltype(
auto) {
return *i; }, current_);
228 template<
typename First2 = First, std::enable_if_t<
229 detail::cartesian_product_is_random_access<Const, First2, Vs...>
::value,
int> = 0>
231 return *((*this) + n);
234 template<std::size_t N =
sizeof...(Vs)>
236 auto& it = std::get<N>(current_);
238 next(it, std::integral_constant<std::size_t, N>{});
241 template<std::size_t N =
sizeof...(Vs)>
243 auto& it = std::get<N>(current_);
244 prev(it, std::integral_constant<std::size_t, N>{});
248 template<
typename Tuple>
250 return scaled_sum(t);
258 template<
typename First2 = First, std::enable_if_t<
264 template<
typename First2 = First, std::enable_if_t<
272 template<
typename First2 = First, std::enable_if_t<
273 detail::cartesian_product_is_bidirectional<Const, First2, Vs...>
::value,
int> = 0>
279 template<
typename First2 = First, std::enable_if_t<
280 detail::cartesian_product_is_bidirectional<Const, First2, Vs...>
::value,
int> = 0>
287 template<
typename First2 = First, std::enable_if_t<
288 detail::cartesian_product_is_random_access<Const, First2, Vs...>
::value,
int> = 0>
304 template<
typename First2 = First, std::enable_if_t<
305 detail::cartesian_product_is_random_access<Const, First2, Vs...>
::value,
int> = 0>
311 template<
typename First2 = First, std::enable_if_t<
314 return x.current_ == y.current_;
317 template<
typename First2 = First, std::enable_if_t<
323 template<
typename First2 = First, std::enable_if_t<
326 return x.compare_with_default();
329 template<
typename First2 = First, std::enable_if_t<
332 return !x.compare_with_default();
335 template<
typename First2 = First, std::enable_if_t<
338 return x.compare_with_default();
341 template<
typename First2 = First, std::enable_if_t<
344 return !x.compare_with_default();
347 template<
typename First2 = First, std::enable_if_t<
348 detail::cartesian_product_is_random_access<Const, First2, Vs...>
::value,
int> = 0>
353 template<
typename First2 = First, std::enable_if_t<
354 detail::cartesian_product_is_random_access<Const, First2, Vs...>
::value,
int> = 0>
359 template<
typename First2 = First, std::enable_if_t<
360 detail::cartesian_product_is_random_access<Const, First2, Vs...>
::value,
int> = 0>
365 template<
typename First2 = First, std::enable_if_t<
366 detail::cartesian_is_sized_sentinel<Const,
iterator_t, First2, Vs...>
::value,
int> = 0>
371 template<
typename First2 = First, std::enable_if_t<
372 detail::cartesian_is_sized_sentinel<Const,
sentinel_t, First2, Vs...>
::value,
int> = 0>
374 return i.distance_from_default();
377 template<
typename First2 = First, std::enable_if_t<
378 detail::cartesian_is_sized_sentinel<Const,
sentinel_t, First2, Vs...>
::value,
int> = 0>
395 template<
typename Dummy =
void, std::enable_if_t<conjunction<std::is_
void<Dummy>,
396 indirectly_swappable< iterator_t<maybe_const<Const, First>> >,
397 indirectly_swappable< iterator_t<maybe_const<Const, Vs>> >...
400 noexcept(noexcept(x.iter_swap_impl(y)))
406 template<
typename It>
407 constexpr
void next(It&, std::integral_constant<std::size_t, 0>) {}
408 template<
typename It, std::
size_t N>
409 constexpr
void next(It& it, std::integral_constant<std::size_t, N>) {
410 if (it ==
ranges::end(std::get<N>(parent_->bases_))) {
416 template<
typename It>
417 constexpr
void prev(It&, std::integral_constant<std::size_t, 0>) {}
418 template<
typename It, std::
size_t N>
419 constexpr
void prev(It& it, std::integral_constant<std::size_t, N>) {
421 it = detail::cartesian_common_arg_end(std::get<N>(parent_->bases_));
426 template<
typename Tuple>
427 constexpr
difference_type scaled_size(
const Tuple& t, std::integral_constant<std::size_t, 0>)
const {
429 return static_cast<difference_type>(std::get<0>(current_) - std::get<0>(t));
431 template<
typename Tuple, std::
size_t N>
432 constexpr
difference_type scaled_size(
const Tuple& t, std::integral_constant<std::size_t, N>)
const {
434 auto g =
static_cast<difference_type>(std::get<N>(current_) - std::get<N>(t));
435 return g + f * scaled_size(t, std::integral_constant<std::size_t, N - 1>{});
438 template<
typename Tuple>
440 return scaled_size(t, std::integral_constant<std::size_t,
sizeof...(Vs)>{});
443 template<std::size_t... I>
444 constexpr
difference_type distance_from_default_impl(std::index_sequence<0, I...>)
const {
451 return distance_from_default_impl(std::index_sequence_for<Vs...>{});
454 constexpr
bool compare_with_default_impl(std::integral_constant<std::size_t, 0>)
const {
455 return std::get<0>(current_) ==
ranges::end(std::get<0>(parent_->bases_));
458 template<std::
size_t I>
459 constexpr
bool compare_with_default_impl(std::integral_constant<std::size_t, I>)
const {
460 return std::get<I>(current_) ==
ranges::end(std::get<I>(parent_->bases_))
462 : compare_with_default(std::integral_constant<std::size_t, I - 1>{});
465 constexpr
bool compare_with_default()
const {
466 return compare_with_default_impl(std::index_sequence_for<Vs...>{});
469 template<std::size_t... I>
470 constexpr
void iter_swap_impl(
const iterator& other, std::index_sequence<I...>)
const
473 noexcept(
ranges::iter_swap(std::get<I>(this->current_), std::get<I>(other.current_)))
483 constexpr
iterator(Parent& parent, iterator_current<Const> current)
486 Parent* parent_ =
nullptr;
487 iterator_current<Const> current_;
495 template<
typename First2 = First, std::enable_if_t<
disjunction<
501 *
this, detail::cartesian_tuple_transform<iterator_current<true>>(
ranges::begin, bases_));
504 template<
typename First2 = First, std::enable_if_t<
conjunction<
510 *
this, detail::cartesian_tuple_transform<iterator_current<true>>(
ranges::begin, bases_));
513 template<
typename First2 = First, std::enable_if_t<
conjunction<
517 detail::cartesian_product_is_common<First, Vs...>
523 template<
typename First2 = First, std::enable_if_t<
524 detail::cartesian_product_is_common<
const First2,
const Vs...>
::value,
int> = 0>
529 template<
typename First2 = First, std::enable_if_t<
530 detail::cartesian_product_is_common<
const First2,
const Vs...>
::value ==
false,
int> = 0>
535 template<
typename First2 = First, std::enable_if_t<
536 detail::cartesian_product_is_sized<First2, Vs...>
::value,
int> = 0>
538 return size_impl(std::index_sequence_for<First, Vs...>{});
541 template<
typename First2 = First, std::enable_if_t<
542 detail::cartesian_product_is_sized<
const First2,
const Vs...>
::value,
int> = 0>
543 constexpr std::size_t
size()
const {
544 return size_impl(std::index_sequence_for<First, Vs...>{});
548 template<std::
size_t N>
549 constexpr
bool is_empty_impl(std::integral_constant<std::size_t, N>)
const {
550 return ranges::empty(std::get<N>(bases_)) ? true : is_empty_impl(std::integral_constant<std::size_t, N - 1>{});
552 constexpr
bool is_empty_impl(std::integral_constant<std::size_t, 0>)
const {
555 constexpr
bool is_empty()
const {
556 return is_empty_impl(std::integral_constant<std::size_t,
sizeof...(Vs)>{});
559 template<
bool Const,
typename Tuple, std::size_t... I>
560 constexpr iterator_current<Const> tuple_transform_end_impl(Tuple&& t, std::index_sequence<0, I...>) {
561 return iterator_current<Const>(
564 detail::cartesian_common_arg_end( std::get<0>(std::forward<Tuple>(t)) ),
569 template<
bool Const,
typename Tuple>
570 constexpr iterator_current<Const> tuple_transform_end(Tuple&& t) {
571 return tuple_transform_end_impl<Const>(
572 std::forward<Tuple>(t),
573 std::make_index_sequence<std::tuple_size<remove_cvref_t<Tuple>>::
value>{});
576 template<
bool Const,
typename Tuple, std::size_t... I>
577 constexpr iterator_current<Const> tuple_transform_end_impl(Tuple&& t, std::index_sequence<0, I...>)
const {
578 return iterator_current<Const>(
581 detail::cartesian_common_arg_end( std::get<0>(std::forward<Tuple>(t)) ),
586 template<
bool Const,
typename Tuple>
587 constexpr iterator_current<Const> tuple_transform_end(Tuple&& t)
const {
588 return tuple_transform_end_impl<Const>(
589 std::forward<Tuple>(t),
590 std::make_index_sequence<std::tuple_size<remove_cvref_t<Tuple>>::
value>{});
593 template<std::size_t... I>
594 constexpr std::size_t size_impl(std::index_sequence<I...>) {
595 std::size_t prod = 1;
597 ((void)(prod *=
static_cast<std::size_t
>(
ranges::size(std::get<I>(bases_)))), 0)...
603 template<std::size_t... I>
604 constexpr std::size_t size_impl(std::index_sequence<I...>)
const {
605 std::size_t prod = 1;
607 ((void)(prod *=
static_cast<std::size_t
>(
ranges::size(std::get<I>(bases_)))), 0)...
614 #if __cplusplus >= 201703L
616 template<
typename... Rs>
617 cartesian_product_view(Rs&&...) -> cartesian_product_view<views::all_t<Rs>...>;
Definition: cartesian_product_view.hpp:187
constexpr friend auto iter_move(const iterator &i) noexcept(noexcept(vccc::tuple_transform(i.current_, ranges::iter_move)) &&conjunction< std::is_nothrow_move_constructible< range_rvalue_reference_t< maybe_const< Const, First > >>, std::is_nothrow_move_constructible< range_rvalue_reference_t< maybe_const< Const, Vs > >>... >::value)
Definition: cartesian_product_view.hpp:383
constexpr iterator & operator--()
Definition: cartesian_product_view.hpp:274
int difference_type
Definition: cartesian_product_view.hpp:208
constexpr friend iterator operator+(const iterator &i, difference_type n)
Definition: cartesian_product_view.hpp:349
constexpr friend iterator operator-(const iterator &i, difference_type n)
Definition: cartesian_product_view.hpp:361
void pointer
Definition: cartesian_product_view.hpp:210
constexpr friend bool operator==(const iterator &x, default_sentinel_t)
Definition: cartesian_product_view.hpp:325
constexpr difference_type distance_from(const Tuple &t) const
Definition: cartesian_product_view.hpp:249
constexpr void operator++(int)
Definition: cartesian_product_view.hpp:260
constexpr iterator(iterator< AntiConst > i)
Definition: cartesian_product_view.hpp:220
constexpr void prev()
Definition: cartesian_product_view.hpp:242
std::tuple< range_reference_t< maybe_const< Const, First > >, range_reference_t< maybe_const< Const, Vs > >... > reference
Definition: cartesian_product_view.hpp:207
constexpr friend bool operator==(const iterator &x, const iterator &y)
Definition: cartesian_product_view.hpp:313
constexpr friend bool operator==(default_sentinel_t, const iterator &x)
Definition: cartesian_product_view.hpp:337
constexpr friend bool operator!=(const iterator &x, const iterator &y)
Definition: cartesian_product_view.hpp:319
constexpr auto operator*() const
Definition: cartesian_product_view.hpp:223
constexpr iterator & operator-=(difference_type n)
Definition: cartesian_product_view.hpp:306
constexpr friend difference_type operator-(default_sentinel_t s, const iterator &i)
Definition: cartesian_product_view.hpp:379
constexpr iterator & operator+=(difference_type n)
Definition: cartesian_product_view.hpp:289
input_iterator_tag iterator_category
Definition: cartesian_product_view.hpp:192
constexpr iterator operator--(int)
Definition: cartesian_product_view.hpp:281
constexpr void next()
Definition: cartesian_product_view.hpp:235
constexpr friend iterator operator+(difference_type n, const iterator &i)
Definition: cartesian_product_view.hpp:355
constexpr friend bool operator!=(default_sentinel_t, const iterator &x)
Definition: cartesian_product_view.hpp:343
constexpr reference operator[](difference_type n) const
Definition: cartesian_product_view.hpp:230
constexpr friend difference_type operator-(const iterator &i, default_sentinel_t)
Definition: cartesian_product_view.hpp:373
constexpr iterator operator++(int)
Definition: cartesian_product_view.hpp:266
constexpr friend bool operator!=(const iterator &x, default_sentinel_t)
Definition: cartesian_product_view.hpp:331
constexpr friend difference_type operator-(const iterator &i, const iterator &j)
Definition: cartesian_product_view.hpp:367
constexpr friend void iter_swap(const iterator &x, const iterator &y) noexcept(noexcept(x.iter_swap_impl(y)))
Definition: cartesian_product_view.hpp:399
constexpr iterator & operator++()
Definition: cartesian_product_view.hpp:253
std::tuple< range_value_t< maybe_const< Const, First > >, range_value_t< maybe_const< Const, Vs > >... > value_type
Definition: cartesian_product_view.hpp:204
std::conditional_t< detail::cartesian_product_is_random_access< Const, First, Vs... >::value, random_access_iterator_tag, std::conditional_t< detail::cartesian_product_is_bidirectional< Const, First, Vs... >::value, bidirectional_iterator_tag, std::conditional_t< forward_range< maybe_const< Const, First > >::value, forward_iterator_tag, input_iterator_tag > >> iterator_concept
Definition: cartesian_product_view.hpp:201
Definition: cartesian_product_view.hpp:170
constexpr default_sentinel_t end() const
Definition: cartesian_product_view.hpp:531
constexpr cartesian_product_view()=default
constexpr cartesian_product_view(First first, Vs... bases)
Definition: cartesian_product_view.hpp:492
constexpr std::size_t size() const
Definition: cartesian_product_view.hpp:543
constexpr std::size_t size()
Definition: cartesian_product_view.hpp:537
constexpr iterator< false > end()
Definition: cartesian_product_view.hpp:519
constexpr iterator< true > begin() const
Definition: cartesian_product_view.hpp:508
constexpr iterator< true > end() const
Definition: cartesian_product_view.hpp:525
constexpr iterator< false > begin()
Definition: cartesian_product_view.hpp:499
helper class template for defining a view, using the curiously recurring template pattern
Definition: view_interface.hpp:78
constexpr VCCC_INLINE_OR_STATIC detail_iter_move::iter_move_niebloid iter_move
Definition: iter_move.hpp:92
constexpr VCCC_INLINE_OR_STATIC detail_iter_swap::iter_swap_niebloid iter_swap
Definition: iter_swap.hpp:90
std::forward_iterator_tag forward_iterator_tag
Definition: iterator_tag.hpp:17
std::random_access_iterator_tag random_access_iterator_tag
Definition: iterator_tag.hpp:19
constexpr VCCC_INLINE_OR_STATIC default_sentinel_t default_sentinel
Definition: default_sentinel_t.hpp:25
std::input_iterator_tag input_iterator_tag
Definition: iterator_tag.hpp:15
std::bidirectional_iterator_tag bidirectional_iterator_tag
Definition: iterator_tag.hpp:18
std::enable_if_t< std::is_object< T >::value, T * > addressof(T &t) noexcept
Definition: addressof.hpp:33
constexpr VCCC_INLINE_OR_STATIC detail::empty_niebloid empty
checks whether a range is empty
Definition: empty.hpp:116
typename sentinel< R >::type sentinel_t
Definition: sentinel_t.hpp:29
typename ranges::iterator< T >::type iterator_t
Definition: iterator_t.hpp:32
constexpr VCCC_INLINE_OR_STATIC detail::begin_niebloid begin
returns an iterator to the beginning of a range
Definition: begin.hpp:116
typename range_rvalue_reference< R >::type range_rvalue_reference_t
Used to obtain the rvalue reference type of the iterator type of range type R.
Definition: range_rvalue_reference_t.hpp:38
constexpr VCCC_INLINE_OR_STATIC detail::distance_niebloid distance
Definition: distance.hpp:72
constexpr VCCC_INLINE_OR_STATIC detail::size_niebloid size
returns the size of a container or array
Definition: size.hpp:145
constexpr VCCC_INLINE_OR_STATIC detail::end_niebloid end
returns a sentinel indicating the end of a range
Definition: end.hpp:120
typename range_reference< R >::type range_reference_t
Used to obtain the reference type of the iterator type of range type R.
Definition: range_reference_t.hpp:42
typename range_value< R >::type range_value_t
Used to obtain the value type of the iterator type of range type R.
Definition: range_value_t.hpp:42
constexpr auto tuple_transform(Tuple &&t, F &&f) noexcept(noexcept(detail::tuple_transform_impl(std::forward< Tuple >(t), std::forward< F >(f), std::make_index_sequence< std::tuple_size< remove_cvref_t< Tuple >>::value >{})))
Constructs a new tuple with each elements transformed.
Definition: tuple_transform.hpp:36
std::integral_constant< bool, v > bool_constant
Definition: bool_constant.hpp:19
std::conditional_t< Const, const V, V > maybe_const
Definition: maybe_const.hpp:16
Definition: matrix.hpp:495
Definition: directory.h:12
constexpr VCCC_INLINE_OR_STATIC detail::element_niebloid< 0 > first
Definition: key_value.hpp:34
constexpr VCCC_INLINE_OR_STATIC detail::element_niebloid< 1 > value
Definition: key_value.hpp:35
Definition: conjunction.hpp:22
Models std::convertible_to
Definition: convertible_to.hpp:38
Definition: default_sentinel_t.hpp:23
Definition: disjunction.hpp:22
specifies that operator == is an equivalence relation
Definition: equality_comparable.hpp:30
Definition: negation.hpp:23
specifies a range whose iterator type satisfies forward_iterator
Definition: forward_range.hpp:47
specifies that a type is a range, that is, it provides a begin iterator and an end sentinel
Definition: range.hpp:53
specifies that a range is a view, that is, it has constant time copy/move/assignment
Definition: view.hpp:31