14#ifndef RANGES_V3_VIEW_JOIN_HPP
15#define RANGES_V3_VIEW_JOIN_HPP
30#include <range/v3/utility/static_const.hpp>
37#include <range/v3/detail/prologue.hpp>
45 constexpr cardinality join_cardinality_(
46 cardinality Outer, cardinality Inner,
47 cardinality Joiner =
static_cast<cardinality
>(0)) noexcept
49 return Outer == infinite || Inner == infinite ||
50 (Joiner == infinite && Outer != 0 && Outer != 1)
52 : Outer == unknown || Inner == unknown ||
53 (Joiner == unknown && Outer != 0 && Outer != 1)
55 : Outer == finite || Inner == finite ||
56 (Joiner == finite && Outer != 0 && Outer != 1)
58 : static_cast<cardinality>(
60 (Outer == 0 ? 0 : (Outer - 1) * Joiner));
63 template<
typename Range>
64 constexpr cardinality join_cardinality() noexcept
66 return detail::join_cardinality_(
67 range_cardinality<Range>::value,
68 range_cardinality<range_reference_t<Range>>::value);
71 template<
typename Range,
typename JoinRange>
72 constexpr cardinality join_cardinality() noexcept
74 return detail::join_cardinality_(
75 range_cardinality<Range>::value,
76 range_cardinality<range_reference_t<Range>>::value,
77 range_cardinality<JoinRange>::value);
80 template<
typename Inner>
83 non_propagating_cache<std::remove_cv_t<Inner>> inner_ = {};
85 template<
typename OuterIt>
86 constexpr auto && update_inner_(OuterIt && it)
88 return inner_.emplace_deref(it);
90 constexpr Inner & get_inner_(ignore_t)
noexcept
96 struct pass_thru_inner_
99 template<
typename OuterIt>
100 static constexpr auto && update_inner_(OuterIt && it)
noexcept
104 template<
typename OuterIt>
105 static constexpr decltype(
auto) get_inner_(OuterIt && outer_it)
111 template<
typename Rng>
112 using join_view_inner =
114 store_inner_<range_reference_t<Rng>>, pass_thru_inner_>;
120 CPP_requires(has_member_arrow_,
129 CPP_concept has_arrow_ =
131 (std::is_pointer<I>::value || CPP_requires_ref(detail::has_member_arrow_, I));
140 template<
typename Rng>
142 :
view_facade<join_view<Rng>, detail::join_cardinality<Rng>()>
143 ,
private detail::join_view_inner<Rng>
150 : outer_(views::all(std::move(rng)))
154 static constexpr auto size()
155 -> CPP_ret(std::size_t)(
156 requires (detail::join_cardinality<Rng>() >= 0))
158 return static_cast<std::size_t
>(detail::join_cardinality<Rng>());
162 constexpr auto CPP_fun(size)()(
163 requires(detail::join_cardinality<Rng>() < 0) &&
168 range_size_t<range_reference_t<Rng>> n = 0;
169 RANGES_FOR(
auto && inner, outer_)
170 n += ranges::size(inner);
174 constexpr Rng base()
const
189 using CInner = range_reference_t<COuter>;
190 using ref_is_glvalue = std::is_reference<CInner>;
192 Parent * rng_ =
nullptr;
198 for(; outer_it_ != ranges::end(rng_->outer_); ++outer_it_)
200 auto && inner = rng_->update_inner_(outer_it_);
201 inner_it_ = ranges::begin(inner);
202 if(inner_it_ != ranges::end(inner))
205 if(RANGES_CONSTEXPR_IF(ref_is_glvalue::value))
211 single_pass_iterator_<iterator_t<CInner>> ||
212 !ref_is_glvalue::value>;
214 template<
typename BeginOrEnd>
215 constexpr cursor(Parent * rng, BeginOrEnd begin_or_end)
217 , outer_it_(begin_or_end(rng->outer_))
221 template(
bool Other)(
222 requires Const AND CPP_NOT(Other) AND
224 convertible_to<iterator_t<range_reference_t<Rng>>,
226 constexpr cursor(cursor<Other> that)
228 , outer_it_(std::move(that.outer_it_))
229 , inner_it_(std::move(that.inner_it_))
232 constexpr auto arrow()
234 requires detail::has_arrow_<iterator_t<CInner>>)
240 return outer_it_ == ranges::end(rng_->outer_);
243 constexpr auto equal(cursor
const & that)
const
245 requires ref_is_glvalue::value &&
246 equality_comparable<iterator_t<COuter>> &&
247 equality_comparable<iterator_t<CInner>>)
249 return outer_it_ == that.outer_it_ && inner_it_ == that.inner_it_;
251 constexpr void next()
253 auto && inner_rng = rng_->get_inner_(outer_it_);
254 if(++inner_it_ == ranges::end(inner_rng))
261 constexpr auto prev()
263 requires ref_is_glvalue::value &&
268 if(outer_it_ == ranges::end(rng_->outer_))
269 inner_it_ = ranges::end(*--outer_it_);
270 while(inner_it_ == ranges::begin(*outer_it_))
271 inner_it_ = ranges::end(*--outer_it_);
275 constexpr auto CPP_auto_fun(read)()(
const)
279 constexpr auto CPP_auto_fun(move)()(
const)
281 return iter_move(inner_it_)
285 static constexpr bool use_const_always()
noexcept
287 return simple_view<Rng>() && std::is_reference<range_reference_t<Rng>>::value;
291 constexpr auto operator()(
join_view * this_, std::true_type)
const
293 return cursor<use_const_always()>{this_, ranges::end};
295 constexpr auto operator()(
join_view *, std::false_type)
const
300 struct cend_cursor_fn
302 constexpr auto operator()(
join_view const * this_, std::true_type)
const
304 return cursor<true>{this_, ranges::end};
306 constexpr auto operator()(
join_view const *, std::false_type)
const
312 constexpr cursor<use_const_always()> begin_cursor()
314 return {
this, ranges::begin};
317 template(
bool Const =
true)(
318 requires Const AND
input_range<meta::const_if_c<Const, Rng>> AND
319 std::is_reference<range_reference_t<meta::const_if_c<Const, Rng>>>::value)
320 constexpr cursor<Const> begin_cursor()
const
322 return {
this, ranges::begin};
325 constexpr auto end_cursor()
331 return end_cursor_fn{}(
this, cond{});
334 template(
bool Const =
true)(
335 requires Const AND
input_range<meta::const_if_c<Const, Rng>> AND
336 std::is_reference<range_reference_t<meta::const_if_c<Const, Rng>>>::value)
337 constexpr auto end_cursor()
const
339 using CRng = meta::const_if_c<Const, Rng>;
345 return cend_cursor_fn{}(
this, cond{});
351 template<
typename Rng,
typename ValRng>
353 :
view_facade<join_with_view<Rng, ValRng>, detail::join_cardinality<Rng, ValRng>()>
354 ,
private detail::join_view_inner<Rng>
360 common_with<range_value_t<range_reference_t<Rng>>, range_value_t<ValRng>>);
361 CPP_assert(semiregular<common_type_t<range_value_t<range_reference_t<Rng>>,
362 range_value_t<ValRng>>>);
366 : outer_(views::all(std::move(rng)))
367 , val_(views::all(std::move(val)))
370 static constexpr auto size()
371 -> CPP_ret(std::size_t)(
372 requires (detail::join_cardinality<Rng, ValRng>() >= 0))
374 return static_cast<std::size_t
>(detail::join_cardinality<Rng, ValRng>());
377 auto CPP_fun(size)()(
const
378 requires(detail::join_cardinality<Rng, ValRng>() < 0) &&
382 range_size_t<range_reference_t<Rng>> n = 0;
383 RANGES_FOR(
auto && inner, outer_)
384 n += ranges::size(inner);
392 using Outer = views::all_t<Rng>;
394 using Inner = views::all_t<range_reference_t<Outer> &>;
397 views::all_t<ValRng> val_{};
409 if(cur_.index() == 0)
411 if(ranges::get<0>(cur_) != ranges::end(rng_->val_))
414 auto && inner = rng_->update_inner_(outer_it_);
415 ranges::emplace<1>(cur_, ranges::begin(inner));
419 auto && inner = rng_->get_inner_(outer_it_);
420 if(ranges::get<1>(cur_) != ranges::end(inner))
422 if(++outer_it_ == ranges::end(rng_->outer_))
424 ranges::emplace<0>(cur_, ranges::begin(rng_->val_));
430 using value_type = common_type_t<range_value_t<Inner>, range_value_t<ValRng>>;
432 common_reference_t<range_reference_t<Inner>, range_reference_t<ValRng>>;
433 using rvalue_reference = common_reference_t<range_rvalue_reference_t<Inner>,
434 range_rvalue_reference_t<ValRng>>;
435 using single_pass = std::true_type;
439 , outer_it_(ranges::begin(rng->outer_))
441 if(outer_it_ != ranges::end(rng->outer_))
443 auto && inner = rng_->update_inner_(outer_it_);
444 ranges::emplace<1>(cur_, ranges::begin(inner));
450 return outer_it_ == ranges::end(rng_->outer_);
455 if(cur_.index() == 0)
457 auto & it = ranges::get<0>(cur_);
458 RANGES_ASSERT(it != ranges::end(rng_->val_));
463 auto & it = ranges::get<1>(cur_);
465 auto && inner = rng_->get_inner_(outer_it_);
466 RANGES_ASSERT(it != ranges::end(inner));
472 reference read()
const
475 if(cur_.index() == 0)
476 return *ranges::get<0>(cur_);
478 return *ranges::get<1>(cur_);
480 rvalue_reference move()
const
484 if(cur_.index() == 0)
485 return iter_move(ranges::get<0>(cur_));
487 return iter_move(ranges::get<1>(cur_));
490 cursor begin_cursor()
504 template(
typename Rng)(
505 concept (joinable_range_)(Rng),
510 template<
typename Rng>
511 CPP_concept joinable_range =
513 CPP_concept_ref(views::joinable_range_, Rng);
517 template(
typename Rng,
typename ValRng)(
518 concept (joinable_with_range_)(Rng, ValRng),
520 range_value_t<ValRng>,
521 range_value_t<range_reference_t<Rng>>> AND
524 range_value_t<ValRng>,
525 range_value_t<range_reference_t<Rng>>>> AND
526 common_reference_with<
527 range_reference_t<ValRng>,
528 range_reference_t<range_reference_t<Rng>>> AND
529 common_reference_with<
530 range_rvalue_reference_t<ValRng>,
531 range_rvalue_reference_t<range_reference_t<Rng>>>
535 template<
typename Rng,
typename ValRng>
536 CPP_concept joinable_with_range =
537 joinable_range<Rng> &&
539 CPP_concept_ref(views::joinable_with_range_, Rng, ValRng);
545 template(
typename Rng)(
546 requires joinable_range<Rng>)
556 template<
typename Rng>
557 using inner_value_t = range_value_t<range_reference_t<Rng>>;
559 using cpp20_join_fn::operator();
561 template(
typename Rng)(
562 requires joinable_with_range<Rng,
single_view<inner_value_t<Rng>>>)
564 operator()(Rng && rng, inner_value_t<Rng> v)
const
566 return {all(
static_cast<Rng &&
>(rng)), single(std::move(v))};
569 template(
typename Rng,
typename ValRng)(
570 requires joinable_with_range<Rng, ValRng>)
572 operator()(Rng && rng, ValRng && val)
const
574 return {all(
static_cast<Rng &&
>(rng)), all(
static_cast<ValRng &&
>(val))};
578 template<
typename Rng,
typename T>
579 invoke_result_t<join_base_fn, Rng, T &>
580 operator()(Rng && rng, detail::reference_wrapper_<T> r)
const
582 return (*
this)(
static_cast<Rng &&
>(rng), r.get());
589 template(
typename T)(
590 requires (!joinable_range<T>))
591 constexpr auto operator()(T && t)
const
593 return make_view_closure(bind_back(
join_base_fn{},
static_cast<T &&
>(t)));
595 template(
typename T)(
596 requires (!joinable_range<T &>) AND
range<T &>)
597 constexpr auto operator()(T & t)
const
600 detail::reference_wrapper_<T>(t)));
607 using join_base_fn::operator();
608 using join_bind_fn::operator();
617#if RANGES_CXX_DEDUCTION_GUIDES >= RANGES_CXX_DEDUCTION_GUIDES_17
618 template(
typename Rng)(
619 requires views::joinable_range<Rng>)
621 ->join_view<views::all_t<Rng>>;
623 template(
typename Rng,
typename ValRng)(
624 requires views::joinable_with_range<Rng, ValRng>)
626 ->join_with_view<views::all_t<Rng>, views::all_t<ValRng>>;
633 RANGES_INLINE_VARIABLE(
636 template(
typename Rng)(
637 requires input_range<Rng> AND view_<Rng> AND
638 input_range<iter_reference_t<iterator_t<Rng>>>)
643#include <range/v3/detail/epilogue.hpp>
645#include <range/v3/detail/satisfy_boost_range.hpp>
The bidirectional_range concept.
The common_range concept.
The forward_range concept.
The viewable_range concept.
decltype(begin(declval(Rng &))) iterator_t
Definition access.hpp:698
std::integral_constant< bool, B > bool_
An integral constant wrapper for bool.
Definition meta.hpp:168
typename detail::_cond< If >::template invoke< Then, Else > conditional_t
Select one type or another depending on a compile-time Boolean.
Definition meta.hpp:1148
Definition default_sentinel.hpp:26
Definition traits.hpp:128
Definition variant.hpp:621
A utility for constructing a view from a (derived) type that implements begin and end cursors.
Definition facade.hpp:66