5 #ifndef VCCC_RANGES_VIEWS_JOIN_WITH_VIEW_HPP_
6 #define VCCC_RANGES_VIEWS_JOIN_WITH_VIEW_HPP_
51 template<
typename RRef,
typename Pattern>
52 using join_with_compatible = conjunction<
53 common_with<range_value_t<RRef>, range_value_t<Pattern>>,
54 common_reference_with<range_reference_t<RRef>, range_reference_t<Pattern>>,
55 common_reference_with<range_rvalue_reference_t<RRef>, range_rvalue_reference_t<Pattern>>
59 class join_with_view_base :
public view_interface<Derived> {
60 struct cache_wrapper {
62 constexpr cache_wrapper(
const I& i) noexcept(
63 std::is_nothrow_constructible<non_propagating_cache<cache_wrapper>, decltype(*i)>::
value)
66 std::remove_cv_t<range_reference_t<V>> val;
69 non_propagating_cache<cache_wrapper> inner_base_{};
72 template<
typename V,
typename Pattern,
typename Derived>
73 class join_with_view_base<V, Pattern, Derived, false> :
public join_with_view_base<V, Pattern, Derived, true> {
75 non_propagating_cache<iterator_t<V>> outer_it_{};
79 template<
typename Base,
typename InnerBase,
typename PatternBase>
80 struct join_with_view_iterator_concept {
81 using iterator_concept =
84 has_typename_type<range_reference<Base>>,
85 std::is_reference<range_reference_t<Base>>,
86 bidirectional_range<Base>,
87 bidirectional_range<InnerBase>,
88 bidirectional_range<PatternBase>,
89 common_range<InnerBase>,
90 common_range<PatternBase>
94 has_typename_type<range_reference<Base>>,
95 std::is_reference<range_reference_t<Base>>,
96 forward_range<InnerBase>,
97 forward_range<PatternBase>
103 template<
typename Base,
typename InnerBase,
typename PatternBase,
104 typename IterConcept = join_with_view_iterator_concept<Base, InnerBase, PatternBase>>
105 struct join_with_view_iterator_category
106 : join_with_view_iterator_concept<Base, InnerBase, PatternBase>
109 #if __cplusplus < 202002L
110 using iterator_category = iterator_ignore;
114 template<
typename Base,
typename InnerBase,
typename PatternBase>
116 : join_with_view_iterator_concept<Base, InnerBase, PatternBase>
119 using OuterC =
typename cxx20_iterator_traits<iterator_t<Base>>::iterator_category;
120 using InnerC =
typename cxx20_iterator_traits<iterator_t<InnerBase>>::iterator_category;
121 using PatternC =
typename cxx20_iterator_traits<iterator_t<PatternBase>>::iterator_category;
124 using iterator_category =
126 negation<std::is_reference<
127 common_reference_t<range_reference_t<InnerBase>, range_reference_t<PatternBase>>
132 derived_from<OuterC, bidirectional_iterator_tag>,
133 derived_from<InnerC, bidirectional_iterator_tag>,
134 derived_from<PatternC, bidirectional_iterator_tag>,
135 common_range<range_reference_t<Base>>,
136 common_range<PatternBase>
141 derived_from<OuterC, forward_iterator_tag>,
142 derived_from<InnerC, forward_iterator_tag>,
143 derived_from<PatternC, forward_iterator_tag>
151 class join_with_view_iterator_base :
public join_with_view_iterator_category<Base, InnerBase, PatternBase> {};
153 template<
typename Base,
typename InnerBase,
typename PatternBase>
154 class join_with_view_iterator_base<Base, InnerBase, PatternBase, true>
155 :
public join_with_view_iterator_category<Base, InnerBase, PatternBase>
158 join_with_view_iterator_base() =
default;
160 constexpr
explicit join_with_view_iterator_base(iterator_t<Base>&& outer_it)
161 : outer_it_(
std::move(outer_it)) {}
163 iterator_t<Base> outer_it_{};
172 template<
typename V,
typename Pattern>
173 class join_with_view :
public detail::join_with_view_base<V, Pattern, join_with_view<V, Pattern>> {
182 template<
bool Const>
class iterator;
184 template<
bool Const>
class sentinel;
189 :
public detail::join_with_view_iterator_base<
190 maybe_const<Const, V>,
191 range_reference_t<maybe_const<Const, V>>,
192 maybe_const<Const, Pattern>>
194 using iterator_base = detail::join_with_view_iterator_base<
217 #if __cplusplus < 202002L
224 template<
bool AntiConst, std::enable_if_t<
conjunction<
231 : iterator_base(
std::move(i.outer_it_)), parent_(i.parent_) {
232 switch (i.inner_it_.
index()) {
234 inner_it_.template emplace<0>(std::move(
235 vccc::detail::variant_raw_get(i.inner_it_._base().union_, in_place_index<0>)));
238 inner_it_.template emplace<1>(std::move(
239 vccc::detail::variant_raw_get(i.inner_it_._base().union_, in_place_index<1>)));
246 constexpr decltype(
auto) operator*()
const {
248 return inner_it_.
visit([](
auto&& it) ->
reference {
return *it; });
252 inner_it_.
visit([](
auto& it) { ++it; });
257 template<
typename IB = InnerBase, std::enable_if_t<
conjunction<
258 std::is_reference<IB>,
266 template<
typename IB = InnerBase, std::enable_if_t<
conjunction<
267 std::is_reference<IB>,
277 template<
typename IB = InnerBase, std::enable_if_t<
conjunction<
278 std::is_reference<IB>,
288 auto& outer_it = get_outer();
291 inner_it_.template emplace<1>(
ranges::end(get_inner()));
295 if (inner_it_.index() == 0) {
296 auto& it = vccc::detail::variant_raw_get(inner_it_._base().union_, in_place_index<0>);
299 inner_it_.template emplace<1>(
ranges::end(get_inner()));
303 }
else if (inner_it_.index() == 1) {
304 auto& it = vccc::detail::variant_raw_get(inner_it_._base().union_, in_place_index<1>);
306 inner_it_.template emplace<0>(
ranges::end(parent_->pattern_));
315 inner_it_.visit([](
auto& it) { --it; });
320 template<
typename IB = InnerBase, std::enable_if_t<
conjunction<
321 std::is_reference<IB>,
334 template<
typename IB = InnerBase, std::enable_if_t<
conjunction<
335 std::is_reference<IB>,
340 if (x.outer_it_ != y.outer_it_) {
344 return x.inner_it_ == y.inner_it_;
347 template<
typename IB = InnerBase, std::enable_if_t<
conjunction<
348 std::is_reference<IB>,
358 return i.inner_it_.visit([](
auto&& i) -> R {
363 template<
typename IS = indirectly_swappable<iterator_t<InnerBase>, iterator_t<PatternBase>>, std::enable_if_t<IS::value,
int> = 0>
374 if (this->outer_it_ !=
ranges::end(parent_->base_)) {
375 inner_it_.template emplace<1>(
ranges::begin(update_inner()));
385 if (*parent_->outer_it_ !=
ranges::end(parent_->base_)) {
386 inner_it_.template emplace<1>(
ranges::begin(update_inner()));
392 constexpr iterator_t<Base>& get_outer() noexcept {
393 return this->outer_it_;
397 constexpr iterator_t<Base>& get_outer() noexcept {
398 return *parent_->outer_it_;
402 constexpr
const iterator_t<Base>& get_outer() const noexcept {
403 return this->outer_it_;
407 constexpr
const iterator_t<Base>& get_outer() const noexcept {
408 return *parent_->outer_it_;
412 constexpr decltype(
auto) update_inner() {
417 constexpr decltype(
auto) update_inner() {
418 return parent_->inner_base_.emplace_deref(get_outer()).val;
422 constexpr decltype(
auto) get_inner() noexcept {
427 constexpr decltype(
auto) get_inner() noexcept {
428 return *parent_->inner_base_.val;
431 constexpr
void satisfy() {
435 if (inner_it_.index() == 0) {
436 if (vccc::detail::variant_raw_get(inner_it_._base().union_, in_place_index<0>) !=
ranges::end(parent_->pattern_)) {
440 inner_it_.template emplace<1>(
ranges::begin(update_inner()));
442 if (vccc::detail::variant_raw_get(inner_it_._base().union_, in_place_index<1>) !=
ranges::end(get_inner())) {
446 auto& outer_it = get_outer();
449 emplace_first_or_not();
453 inner_it_.template emplace<0>(
ranges::begin(parent_->pattern_));
459 constexpr
void emplace_first_or_not() {
460 inner_it_.template emplace<0>();
464 constexpr
void emplace_first_or_not() { }
467 variant<iterator_t<PatternBase>, iterator_t<InnerBase>> inner_it_{};
480 template<
bool AntiConst, std::enable_if_t<
conjunction<
485 : end_(
std::move(i.end_)) {}
504 constexpr
explicit sentinel(Parent& parent)
505 : end_(ranges::
end(parent.base_)) {}
507 constexpr
bool equal(
const iterator<Const>& x)
const {
509 return x.get_outer() == end_;
512 sentinel_t<Base> end_{};
518 : base_(
std::move(
base)), pattern_(
std::move(pattern)) {}
525 : base_(views::
all(
std::forward<R>(r))), pattern_(views::
single(
std::move(
e))) {}
534 return std::move(base_);
542 std::is_reference<range_reference_t<V2>>
553 template<
typename V2 = V, std::enable_if_t<
conjunction<
556 std::is_reference<range_reference_t<const V2>>
562 template<
typename V2 = V, std::enable_if_t<
conjunction<
564 std::is_reference<range_reference_t<V2>>,
574 template<
typename V2 = V, std::enable_if_t<
conjunction<
576 std::is_reference<range_reference_t<V2>>,
586 template<
typename V2 = V, std::enable_if_t<
conjunction<
589 std::is_reference<range_reference_t<const V2>>
591 constexpr
auto end()
const {
600 constexpr
auto end_impl(std::true_type)
const {
603 constexpr
auto end_impl(std::false_type)
const {
604 return sentinel<true>{*
this};
611 #if __cplusplus >= 201703L
613 template<
typename R,
typename P>
614 join_with_view(R&&, P&&) -> join_with_view<views::all_t<R>, views::all_t<P>>;
618 -> join_with_view<views::all_t<R>, single_view<range_value_t<range_reference_t<R>>>>;
Definition: bad_variant_access.hpp:15
Definition: join_with_view.hpp:193
constexpr iterator & operator--()
Definition: join_with_view.hpp:285
common_type_t< range_difference_t< Base >, range_difference_t< InnerBase >, range_difference_t< PatternBase > > difference_type
Definition: join_with_view.hpp:216
void pointer
Definition: join_with_view.hpp:218
constexpr friend void iter_swap(const iterator &x, const iterator &y)
Definition: join_with_view.hpp:364
constexpr void operator++(int)
Definition: join_with_view.hpp:262
constexpr iterator(iterator< AntiConst > i)
Definition: join_with_view.hpp:230
constexpr friend bool operator==(const iterator &x, const iterator &y)
Definition: join_with_view.hpp:339
constexpr friend bool operator!=(const iterator &x, const iterator &y)
Definition: join_with_view.hpp:352
common_type_t< range_value_t< InnerBase >, range_value_t< PatternBase > > value_type
Definition: join_with_view.hpp:212
friend class sentinel
Definition: join_with_view.hpp:200
common_reference_t< range_reference_t< InnerBase >, range_reference_t< PatternBase > > reference
Definition: join_with_view.hpp:219
constexpr iterator operator--(int)
Definition: join_with_view.hpp:328
friend class join_with_view
Definition: join_with_view.hpp:199
constexpr iterator operator++(int)
Definition: join_with_view.hpp:271
constexpr iterator & operator++()
Definition: join_with_view.hpp:251
constexpr decltype(auto) friend iter_move(const iterator &i)
Definition: join_with_view.hpp:356
Definition: join_with_view.hpp:471
constexpr sentinel(sentinel< AntiConst > i)
Definition: join_with_view.hpp:484
constexpr friend bool operator==(const sentinel &y, const iterator< Const > &x)
Definition: join_with_view.hpp:495
constexpr friend bool operator==(const iterator< Const > &x, const sentinel &y)
Definition: join_with_view.hpp:487
constexpr friend bool operator!=(const iterator< Const > &x, const sentinel &y)
Definition: join_with_view.hpp:491
constexpr friend bool operator!=(const sentinel &y, const iterator< Const > &x)
Definition: join_with_view.hpp:499
Definition: join_with_view.hpp:173
constexpr V base() const &
Definition: join_with_view.hpp:529
constexpr join_with_view(V base, Pattern pattern)
Definition: join_with_view.hpp:517
constexpr V base() &&
Definition: join_with_view.hpp:533
constexpr auto end()
Definition: join_with_view.hpp:569
constexpr join_with_view(R &&r, range_value_t< range_reference_t< V >> e)
Definition: join_with_view.hpp:524
constexpr auto end() const
Definition: join_with_view.hpp:591
constexpr iterator< true > begin() const
Definition: join_with_view.hpp:558
constexpr iterator< false > begin()
Definition: join_with_view.hpp:548
constexpr auto begin()
Definition: join_with_view.hpp:538
constexpr std::size_t index() const noexcept
Definition: variant.hpp:662
constexpr decltype(auto) visit(Visitor &&vis) &
Definition: variant.hpp:707
constexpr VCCC_INLINE_OR_STATIC detail::equal_niebloid equal
Two ranges are considered equal if they have the same number of elements and every pair of correspond...
Definition: equal.hpp:142
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::input_iterator_tag input_iterator_tag
Definition: iterator_tag.hpp:15
std::bidirectional_iterator_tag bidirectional_iterator_tag
Definition: iterator_tag.hpp:18
constexpr T e
the mathematical constant
Definition: constants.hpp:37
std::enable_if_t< std::is_object< T >::value, T * > addressof(T &t) noexcept
Definition: addressof.hpp:33
constexpr VCCC_INLINE_OR_STATIC detail::single_niebloid single
Definition: single.hpp:104
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::end_niebloid end
returns a sentinel indicating the end of a range
Definition: end.hpp:120
typename range_difference< R >::type range_difference_t
Used to obtain the difference type of the iterator type of range type R.
Definition: range_difference_t.hpp:41
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
constexpr VCCC_INLINE_OR_STATIC detail::all_adaptor_closure all
a view that includes all elements of a range
Definition: all.hpp:82
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
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
constexpr R visit(Visitor &&vis, Variants &&... vars)
Definition: visit.hpp:93
Definition: matrix.hpp:495
Definition: cxx20_rel_ops.hpp:17
Definition: directory.h:12
constexpr VCCC_INLINE_OR_STATIC detail::element_niebloid< 1 > value
Definition: key_value.hpp:35
Definition: conjunction.hpp:22
specifies that a variable of the type can be constructed from or bound to a set of argument types
Definition: constructible_from.hpp:31
Models std::convertible_to
Definition: convertible_to.hpp:38
specifies that operator == is an equivalence relation
Definition: equality_comparable.hpp:30
specifies that an input_iterator is a forward iterator, supporting equality comparison and multi-pass
Definition: forward_iterator.hpp:53
specifies a range whose iterator type satisfies bidirectional_iterator
Definition: bidirectional_range.hpp:49
Definition: common_range.hpp:41
specifies a range whose iterator type satisfies forward_iterator
Definition: forward_range.hpp:47
Definition: simple_view.hpp:28
specifies that a range is a view, that is, it has constant time copy/move/assignment
Definition: view.hpp:31