14 #ifndef RANGES_V3_VIEW_JOIN_HPP
15 #define RANGES_V3_VIEW_JOIN_HPP
17 #include <type_traits>
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>
145 CPP_assert(input_range<Rng> && view_<Rng>);
150 : outer_(views::all(std::move(rng)))
154 static constexpr
auto size()
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) &&
165 forward_range<Rng> &&
168 range_size_t<range_reference_t<Rng>> n = 0;
169 RANGES_FOR(
auto && inner, outer_)
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 &&
264 bidirectional_range<COuter> &&
265 bidirectional_range<CInner> &&
266 common_range<CInner>)
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()
329 forward_range<Rng> && forward_range<range_reference_t<Rng>> &&
330 common_range<Rng> && common_range<range_reference_t<Rng>>>;
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>;
342 forward_range<CRng> &&
343 forward_range<range_reference_t<CRng>> &&
344 common_range<CRng> && common_range<range_reference_t<CRng>>>;
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>
356 CPP_assert(input_range<Rng>);
358 CPP_assert(forward_range<ValRng>);
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()
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) &&
380 sized_range<range_reference_t<Rng>> && sized_range<ValRng>)
382 range_size_t<range_reference_t<Rng>> n = 0;
383 RANGES_FOR(
auto && inner, outer_)
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 =
512 viewable_range<Rng> && input_range<Rng> &&
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> &&
538 viewable_range<ValRng> && forward_range<ValRng> &&
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
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>>;
636 template(
typename Rng)(
637 requires input_range<Rng> AND view_<Rng> AND
643 #include <range/v3/detail/epilogue.hpp>
645 #include <range/v3/detail/satisfy_boost_range.hpp>
CPP_concept sized_range
\concept sized_range
Definition: concepts.hpp:208
CPP_concept input_range
\concept input_range
Definition: concepts.hpp:103
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
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
defer< bind_back, Fn, Ts... > bind_back
Definition: meta.hpp:994
meta::size_t< L::size()> size
An integral constant wrapper that is the size of the meta::list L.
Definition: meta.hpp:1696
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: single.hpp:41
Definition: variant.hpp:621
A utility for constructing a view from a (derived) type that implements begin and end cursors.
Definition: facade.hpp:66