366 lines
30 KiB
Markdown
366 lines
30 KiB
Markdown
[range.join.with]
|
||
|
||
# 25 Ranges library [[ranges]](./#ranges)
|
||
|
||
## 25.7 Range adaptors [[range.adaptors]](range.adaptors#range.join.with)
|
||
|
||
### 25.7.15 Join with view [range.join.with]
|
||
|
||
#### [25.7.15.1](#overview) Overview [[range.join.with.overview]](range.join.with.overview)
|
||
|
||
[1](#overview-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L7186)
|
||
|
||
join_with_view takes a view and a delimiter, and
|
||
flattens the view,
|
||
inserting every element of the delimiter
|
||
in between elements of the view[.](#overview-1.sentence-1)
|
||
|
||
The delimiter can be a single element or a view of elements[.](#overview-1.sentence-2)
|
||
|
||
[2](#overview-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L7193)
|
||
|
||
The name views::join_with denotes
|
||
a range adaptor object ([[range.adaptor.object]](range.adaptor.object "25.7.2 Range adaptor objects"))[.](#overview-2.sentence-1)
|
||
|
||
Given subexpressions E and F,
|
||
the expression views::join_with(E, F) is expression-equivalent tojoin_with_view(E, F)[.](#overview-2.sentence-2)
|
||
|
||
[3](#overview-3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L7201)
|
||
|
||
[*Example [1](#overview-example-1)*: vector<string> vs = {"the", "quick", "brown", "fox"};for (char c : vs | views::join_with('-')) { cout << c;}// The above prints the-quick-brown-fox â *end example*]
|
||
|
||
#### [25.7.15.2](#view) Class template join_with_view [[range.join.with.view]](range.join.with.view)
|
||
|
||
[ð](#lib:join_with_view)
|
||
|
||
namespace std::ranges {template<class R>concept [*bidirectional-common*](#concept:bidirectional-common "25.7.15.2 Class template join_with_view [range.join.with.view]") = [bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]")<R> && [common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]")<R>; // *exposition only*template<[input_range](range.refinements#concept:input_range "25.4.6 Other range refinements [range.refinements]") V, [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]") Pattern>requires [view](range.view#concept:view "25.4.5 Views [range.view]")<V> && [input_range](range.refinements#concept:input_range "25.4.6 Other range refinements [range.refinements]")<range_reference_t<V>>&& [view](range.view#concept:view "25.4.5 Views [range.view]")<Pattern>&& [*concatable*](range.concat.view#concept:concatable "25.7.18.2 Class template concat_view [range.concat.view]")<range_reference_t<V>, Pattern>class join_with_view : public view_interface<join_with_view<V, Pattern>> {using *InnerRng* = range_reference_t<V>; // *exposition only* V *base_* = V(); // *exposition only**non-propagating-cache*<iterator_t<V>> *outer_it_*; // *exposition only*, present only// when <V>*non-propagating-cache*<remove_cv_t<*InnerRng*>> *inner_*; // *exposition only*, present only// if is_reference_v<*InnerRng*> is false Pattern *pattern_* = Pattern(); // *exposition only*// [[range.join.with.iterator]](#iterator "25.7.15.3 Class template join_with_view::iterator"), class template join_with_view::*iterator*template<bool Const> struct *iterator*; // *exposition only*// [[range.join.with.sentinel]](#sentinel "25.7.15.4 Class template join_with_view::sentinel"), class template join_with_view::*sentinel*template<bool Const> struct *sentinel*; // *exposition only*public: join_with_view()requires [default_initializable](concept.default.init#concept:default_initializable "18.4.12 Concept default_initializable [concept.default.init]")<V> && [default_initializable](concept.default.init#concept:default_initializable "18.4.12 Concept default_initializable [concept.default.init]")<Pattern> = default; constexpr explicit join_with_view(V base, Pattern pattern); template<[input_range](range.refinements#concept:input_range "25.4.6 Other range refinements [range.refinements]") R>requires [constructible_from](concept.constructible#concept:constructible_from "18.4.11 Concept constructible_from [concept.constructible]")<V, views::all_t<R>> &&[constructible_from](concept.constructible#concept:constructible_from "18.4.11 Concept constructible_from [concept.constructible]")<Pattern, single_view<range_value_t<*InnerRng*>>>constexpr explicit join_with_view(R&& r, range_value_t<*InnerRng*> e); constexpr V base() const & requires [copy_constructible](concept.copyconstructible#concept:copy_constructible "18.4.14 Concept copy_constructible [concept.copyconstructible]")<V> { return *base_*; }constexpr V base() && { return std::move(*base_*); }constexpr auto begin() {if constexpr ([forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]")<V>) {constexpr bool use_const =[*simple-view*](range.utility.helpers#concept:simple-view "25.5.2 Helper concepts [range.utility.helpers]")<V> && is_reference_v<*InnerRng*> && [*simple-view*](range.utility.helpers#concept:simple-view "25.5.2 Helper concepts [range.utility.helpers]")<Pattern>; return *iterator*<use_const>{*this, ranges::begin(*base_*)}; }else {*outer_it_* = ranges::begin(*base_*); return *iterator*<false>{*this}; }}constexpr auto begin() constrequires [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]")<const V> &&[forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]")<const Pattern> && is_reference_v<range_reference_t<const V>> &&[input_range](range.refinements#concept:input_range "25.4.6 Other range refinements [range.refinements]")<range_reference_t<const V>> &&[*concatable*](range.concat.view#concept:concatable "25.7.18.2 Class template concat_view [range.concat.view]")<range_reference_t<const V>, const Pattern> {return *iterator*<true>{*this, ranges::begin(*base_*)}; }constexpr auto end() {if constexpr ([forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]")<V> && is_reference_v<*InnerRng*> && [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]")<*InnerRng*> &&[common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]")<V> && [common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]")<*InnerRng*>)return *iterator*<[*simple-view*](range.utility.helpers#concept:simple-view "25.5.2 Helper concepts [range.utility.helpers]")<V> && [*simple-view*](range.utility.helpers#concept:simple-view "25.5.2 Helper concepts [range.utility.helpers]")<Pattern>>{*this, ranges::end(*base_*)}; elsereturn *sentinel*<[*simple-view*](range.utility.helpers#concept:simple-view "25.5.2 Helper concepts [range.utility.helpers]")<V> && [*simple-view*](range.utility.helpers#concept:simple-view "25.5.2 Helper concepts [range.utility.helpers]")<Pattern>>{*this}; }constexpr auto end() constrequires [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]")<const V> && [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]")<const Pattern> && is_reference_v<range_reference_t<const V>> &&[input_range](range.refinements#concept:input_range "25.4.6 Other range refinements [range.refinements]")<range_reference_t<const V>> &&[*concatable*](range.concat.view#concept:concatable "25.7.18.2 Class template concat_view [range.concat.view]")<range_reference_t<const V>, const Pattern> {using InnerConstRng = range_reference_t<const V>; if constexpr ([forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]")<InnerConstRng> &&[common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]")<const V> && [common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]")<InnerConstRng>)return *iterator*<true>{*this, ranges::end(*base_*)}; elsereturn *sentinel*<true>{*this}; }}; template<class R, class P> join_with_view(R&&, P&&) -> join_with_view<views::all_t<R>, views::all_t<P>>; template<[input_range](range.refinements#concept:input_range "25.4.6 Other range refinements [range.refinements]") R> join_with_view(R&&, range_value_t<range_reference_t<R>>)-> join_with_view<views::all_t<R>, single_view<range_value_t<range_reference_t<R>>>>;}
|
||
|
||
[ð](#lib:join_with_view,constructor)
|
||
|
||
`constexpr explicit join_with_view(V base, Pattern pattern);
|
||
`
|
||
|
||
[1](#view-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L7311)
|
||
|
||
*Effects*: Initializes *base_* with std::move(base) and*pattern_* with std::move(pattern)[.](#view-1.sentence-1)
|
||
|
||
[ð](#lib:join_with_view,constructor_)
|
||
|
||
`template<[input_range](range.refinements#concept:input_range "25.4.6 Other range refinements [range.refinements]") R>
|
||
requires [constructible_from](concept.constructible#concept:constructible_from "18.4.11 Concept constructible_from [concept.constructible]")<V, views::all_t<R>> &&
|
||
[constructible_from](concept.constructible#concept:constructible_from "18.4.11 Concept constructible_from [concept.constructible]")<Pattern, single_view<range_value_t<InnerRng>>>
|
||
constexpr explicit join_with_view(R&& r, range_value_t<InnerRng> e);
|
||
`
|
||
|
||
[2](#view-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L7326)
|
||
|
||
*Effects*: Initializes *base_* with views::all(std::forward<R>(r)) and*pattern_* with views::single(std::move(e))[.](#view-2.sentence-1)
|
||
|
||
#### [25.7.15.3](#iterator) Class template join_with_view::*iterator* [[range.join.with.iterator]](range.join.with.iterator)
|
||
|
||
[ð](#lib:join_with_view::iterator)
|
||
|
||
namespace std::ranges {template<[input_range](range.refinements#concept:input_range "25.4.6 Other range refinements [range.refinements]") V, [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]") Pattern>requires [view](range.view#concept:view "25.4.5 Views [range.view]")<V> && [input_range](range.refinements#concept:input_range "25.4.6 Other range refinements [range.refinements]")<range_reference_t<V>>&& [view](range.view#concept:view "25.4.5 Views [range.view]")<Pattern> && [*concatable*](range.concat.view#concept:concatable "25.7.18.2 Class template concat_view [range.concat.view]")<range_reference_t<V>, Pattern>template<bool Const>class join_with_view<V, Pattern>::*iterator* {using *Parent* = *maybe-const*<Const, join_with_view>; // *exposition only*using *Base* = *maybe-const*<Const, V>; // *exposition only*using *InnerBase* = range_reference_t<*Base*>; // *exposition only*using *PatternBase* = *maybe-const*<Const, Pattern>; // *exposition only*using *OuterIter* = iterator_t<*Base*>; // *exposition only*using *InnerIter* = iterator_t<*InnerBase*>; // *exposition only*using *PatternIter* = iterator_t<*PatternBase*>; // *exposition only*static constexpr bool *ref-is-glvalue* = is_reference_v<*InnerBase*>; // *exposition only**Parent** *parent_* = nullptr; // *exposition only**OuterIter* *outer_it_* = *OuterIter*(); // *exposition only*, present only// if *Base* models [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]") variant<*PatternIter*, *InnerIter*> *inner_it_*; // *exposition only*constexpr *iterator*(*Parent*& parent, *OuterIter* outer)requires [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]")<*Base*>; // *exposition only*constexpr explicit *iterator*(*Parent*& parent)requires (<*Base*>); // *exposition only*constexpr *OuterIter*& *outer*(); // *exposition only*constexpr const *OuterIter*& *outer*() const; // *exposition only*constexpr auto& *update-inner*(); // *exposition only*constexpr auto& *get-inner*(); // *exposition only*constexpr void *satisfy*(); // *exposition only*public:using iterator_concept = *see below*; using iterator_category = *see below*; // not always presentusing value_type = *see below*; using difference_type = *see below*; *iterator*() = default; constexpr *iterator*(*iterator*<!Const> i)requires Const && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_to [concept.convertible]")<iterator_t<V>, *OuterIter*> &&[convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_to [concept.convertible]")<iterator_t<*InnerRng*>, *InnerIter*> &&[convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_to [concept.convertible]")<iterator_t<Pattern>, *PatternIter*>; constexpr decltype(auto) operator*() const; constexpr *iterator*& operator++(); constexpr void operator++(int); constexpr *iterator* operator++(int)requires *ref-is-glvalue* && [forward_iterator](iterator.concept.forward#concept:forward_iterator "24.3.4.11 Concept forward_iterator [iterator.concept.forward]")<*OuterIter*> &&[forward_iterator](iterator.concept.forward#concept:forward_iterator "24.3.4.11 Concept forward_iterator [iterator.concept.forward]")<*InnerIter*>; constexpr *iterator*& operator--()requires *ref-is-glvalue* && [bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]")<*Base*> &&[*bidirectional-common*](#concept:bidirectional-common "25.7.15.2 Class template join_with_view [range.join.with.view]")<*InnerBase*> && [*bidirectional-common*](#concept:bidirectional-common "25.7.15.2 Class template join_with_view [range.join.with.view]")<*PatternBase*>; constexpr *iterator* operator--(int)requires *ref-is-glvalue* && [bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]")<*Base*> &&[*bidirectional-common*](#concept:bidirectional-common "25.7.15.2 Class template join_with_view [range.join.with.view]")<*InnerBase*> && [*bidirectional-common*](#concept:bidirectional-common "25.7.15.2 Class template join_with_view [range.join.with.view]")<*PatternBase*>; friend constexpr bool operator==(const *iterator*& x, const *iterator*& y)requires *ref-is-glvalue* && [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]")<*Base*> &&[equality_comparable](concept.equalitycomparable#concept:equality_comparable "18.5.4 Concept equality_comparable [concept.equalitycomparable]")<*InnerIter*>; friend constexpr decltype(auto) iter_move(const *iterator*& x) {using rvalue_reference = common_reference_t< iter_rvalue_reference_t<*InnerIter*>,
|
||
iter_rvalue_reference_t<*PatternIter*>>; return visit<rvalue_reference>(ranges::iter_move, x.*inner_it_*); }friend constexpr void iter_swap(const *iterator*& x, const *iterator*& y)requires [indirectly_swappable](alg.req.ind.swap#concept:indirectly_swappable "24.3.7.4 Concept indirectly_swappable [alg.req.ind.swap]")<*InnerIter*, *PatternIter*> { visit(ranges::iter_swap, x.*inner_it_*, y.*inner_it_*); }};}
|
||
|
||
[1](#iterator-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L7414)
|
||
|
||
*iterator*::iterator_concept is defined as follows:
|
||
|
||
- [(1.1)](#iterator-1.1)
|
||
|
||
If *ref-is-glvalue* is true,*Base* models [bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]"), and*InnerBase* and *PatternBase* each model [*bidirectional-common*](#concept:bidirectional-common "25.7.15.2 Class template join_with_view [range.join.with.view]"),
|
||
then iterator_concept denotes bidirectional_iterator_tag[.](#iterator-1.1.sentence-1)
|
||
|
||
- [(1.2)](#iterator-1.2)
|
||
|
||
Otherwise, if *ref-is-glvalue* is true and*Base* and *InnerBase* each model [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]"),
|
||
then iterator_concept denotes forward_iterator_tag[.](#iterator-1.2.sentence-1)
|
||
|
||
- [(1.3)](#iterator-1.3)
|
||
|
||
Otherwise, iterator_concept denotes input_iterator_tag[.](#iterator-1.3.sentence-1)
|
||
|
||
[2](#iterator-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L7431)
|
||
|
||
The member [*typedef-name*](dcl.typedef#nt:typedef-name "9.2.4 The typedef specifier [dcl.typedef]") iterator_category is defined
|
||
if and only if *ref-is-glvalue* is true, and*Base* and *InnerBase* each model [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]")[.](#iterator-2.sentence-1)
|
||
|
||
In that case,*iterator*::iterator_category is defined as follows:
|
||
|
||
- [(2.1)](#iterator-2.1)
|
||
|
||
Let *OUTERC* denoteiterator_traits<*OuterIter*>::iterator_category,
|
||
let *INNERC* denoteiterator_traits<*InnerIter*>::iterator_category, and
|
||
let *PATTERNC* denoteiterator_traits<*PatternIter*>::iterator_category[.](#iterator-2.1.sentence-1)
|
||
|
||
- [(2.2)](#iterator-2.2)
|
||
|
||
Ifis_reference_v<common_reference_t<iter_reference_t<*InnerIter*>,
|
||
iter_reference_t<*PatternIter*>>> is false,iterator_category denotes input_iterator_tag[.](#iterator-2.2.sentence-1)
|
||
|
||
- [(2.3)](#iterator-2.3)
|
||
|
||
Otherwise,
|
||
if *OUTERC*, *INNERC*, and *PATTERNC* each model [derived_from](concept.derived#concept:derived_from "18.4.3 Concept derived_from [concept.derived]")<bidirectional_iterator_tag> and *InnerBase* and *PatternBase* each model [common_range](range.refinements#concept:common_range "25.4.6 Other range refinements [range.refinements]"),iterator_category denotes bidirectional_iterator_tag[.](#iterator-2.3.sentence-1)
|
||
|
||
- [(2.4)](#iterator-2.4)
|
||
|
||
Otherwise,
|
||
if *OUTERC*, *INNERC*, and *PATTERNC* each model [derived_from](concept.derived#concept:derived_from "18.4.3 Concept derived_from [concept.derived]")<forward_iterator_tag>,iterator_category denotes forward_iterator_tag[.](#iterator-2.4.sentence-1)
|
||
|
||
- [(2.5)](#iterator-2.5)
|
||
|
||
Otherwise, iterator_category denotes input_iterator_tag[.](#iterator-2.5.sentence-1)
|
||
|
||
[3](#iterator-3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L7469)
|
||
|
||
*iterator*::value_type denotes the type:common_type_t<iter_value_t<*InnerIter*>, iter_value_t<*PatternIter*>>
|
||
|
||
[4](#iterator-4)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L7475)
|
||
|
||
*iterator*::difference_type denotes the type:common_type_t< iter_difference_t<*OuterIter*>,
|
||
iter_difference_t<*InnerIter*>,
|
||
iter_difference_t<*PatternIter*>>
|
||
|
||
[ð](#lib:outer,join_with_view::iterator)
|
||
|
||
`constexpr OuterIter& outer();
|
||
constexpr const OuterIter& outer() const;
|
||
`
|
||
|
||
[5](#iterator-5)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L7491)
|
||
|
||
*Returns*: *outer_it_* if *Base* models [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]");
|
||
otherwise, **parent_*->*outer_it_*[.](#iterator-5.sentence-1)
|
||
|
||
[ð](#lib:update-inner,join_with_view::iterator)
|
||
|
||
`constexpr auto& update-inner();
|
||
`
|
||
|
||
[6](#iterator-6)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L7503)
|
||
|
||
*Effects*: Equivalent to:if constexpr (*ref-is-glvalue*)return *as-lvalue*(**outer*());elsereturn *parent_*->*inner_*.*emplace-deref*(*outer*());
|
||
|
||
[ð](#lib:get-inner,join_with_view::iterator)
|
||
|
||
`constexpr auto& get-inner();
|
||
`
|
||
|
||
[7](#iterator-7)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L7520)
|
||
|
||
*Effects*: Equivalent to:if constexpr (*ref-is-glvalue*)return *as-lvalue*(**outer*());elsereturn **parent_*->*inner_*;
|
||
|
||
[ð](#lib:satisfy,join_with_view::iterator)
|
||
|
||
`constexpr void satisfy();
|
||
`
|
||
|
||
[8](#iterator-8)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L7537)
|
||
|
||
*Effects*: Equivalent to:while (true) {if (*inner_it_*.index() == 0) {if (std::get<0>(*inner_it_*) != ranges::end(*parent_*->*pattern_*))break; *inner_it_*.template emplace<1>(ranges::begin(*update-inner*())); } else {if (std::get<1>(*inner_it_*) != ranges::end(*get-inner*()))break; if (++*outer*() == ranges::end(*parent_*->*base_*)) {if constexpr (*ref-is-glvalue*)*inner_it_*.template emplace<0>(); break; }*inner_it_*.template emplace<0>(ranges::begin(*parent_*->*pattern_*)); }}
|
||
|
||
[*Note [1](#iterator-note-1)*:
|
||
|
||
join_with_view iterators use the *satisfy* function
|
||
to skip over empty inner ranges[.](#iterator-8.sentence-2)
|
||
|
||
â *end note*]
|
||
|
||
[ð](#lib:join_with_view::iterator,constructor)
|
||
|
||
`constexpr iterator(Parent& parent, OuterIter outer)
|
||
requires [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]")<Base>;
|
||
constexpr explicit iterator(Parent& parent)
|
||
requires (<Base>);
|
||
`
|
||
|
||
[9](#iterator-9)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L7574)
|
||
|
||
*Effects*: Initializes *parent_* with addressof(parent)[.](#iterator-9.sentence-1)
|
||
|
||
For the first overload, also initializes*outer_it_* with std::move(outer)[.](#iterator-9.sentence-2)
|
||
|
||
Then, equivalent to:if (*outer*() != ranges::end(*parent_*->*base_*)) {*inner_it_*.template emplace<1>(ranges::begin(*update-inner*())); *satisfy*();}
|
||
|
||
[ð](#lib:join_with_view::iterator,constructor_)
|
||
|
||
`constexpr iterator(iterator<!Const> i)
|
||
requires Const && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_to [concept.convertible]")<iterator_t<V>, OuterIter> &&
|
||
[convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_to [concept.convertible]")<iterator_t<InnerRng>, InnerIter> &&
|
||
[convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_to [concept.convertible]")<iterator_t<Pattern>, PatternIter>;
|
||
`
|
||
|
||
[10](#iterator-10)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L7597)
|
||
|
||
*Effects*: Initializes *outer_it_* withstd::move(i.*outer_it_*) and*parent_* with i.*parent_*[.](#iterator-10.sentence-1)
|
||
|
||
Then, equivalent to:if (i.*inner_it_*.index() == 0)*inner_it_*.template emplace<0>(std::get<0>(std::move(i.*inner_it_*)));else*inner_it_*.template emplace<1>(std::get<1>(std::move(i.*inner_it_*)));
|
||
|
||
[11](#iterator-11)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L7610)
|
||
|
||
[*Note [2](#iterator-note-2)*:
|
||
|
||
Const can only be true when *Base* models [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]")[.](#iterator-11.sentence-1)
|
||
|
||
â *end note*]
|
||
|
||
[ð](#lib:operator--,join_with_view::iterator)
|
||
|
||
`constexpr decltype(auto) operator*() const;
|
||
`
|
||
|
||
[12](#iterator-12)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L7623)
|
||
|
||
*Effects*: Equivalent to:using reference = common_reference_t<iter_reference_t<*InnerIter*>, iter_reference_t<*PatternIter*>>;return visit([](auto& it) -> reference { return *it; }, *inner_it_*);
|
||
|
||
[ð](#lib:operator++,join_with_view::iterator)
|
||
|
||
`constexpr iterator& operator++();
|
||
`
|
||
|
||
[13](#iterator-13)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L7639)
|
||
|
||
*Effects*: Equivalent to:visit([](auto& it){ ++it; }, *inner_it_*);*satisfy*();return *this;
|
||
|
||
[ð](#lib:operator++,join_with_view::iterator_)
|
||
|
||
`constexpr void operator++(int);
|
||
`
|
||
|
||
[14](#iterator-14)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L7655)
|
||
|
||
*Effects*: Equivalent to ++*this[.](#iterator-14.sentence-1)
|
||
|
||
[ð](#lib:operator++,join_with_view::iterator__)
|
||
|
||
`constexpr iterator operator++(int)
|
||
requires ref-is-glvalue && [forward_iterator](iterator.concept.forward#concept:forward_iterator "24.3.4.11 Concept forward_iterator [iterator.concept.forward]")<OuterIter> && [forward_iterator](iterator.concept.forward#concept:forward_iterator "24.3.4.11 Concept forward_iterator [iterator.concept.forward]")<InnerIter>;
|
||
`
|
||
|
||
[15](#iterator-15)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L7667)
|
||
|
||
*Effects*: Equivalent to:*iterator* tmp = *this;++*this;return tmp;
|
||
|
||
[ð](#lib:operator--,join_with_view::iterator_)
|
||
|
||
`constexpr iterator& operator--()
|
||
requires ref-is-glvalue && [bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]")<Base> &&
|
||
[bidirectional-common](#concept:bidirectional-common "25.7.15.2 Class template join_with_view [range.join.with.view]")<InnerBase> && [bidirectional-common](#concept:bidirectional-common "25.7.15.2 Class template join_with_view [range.join.with.view]")<PatternBase>;
|
||
`
|
||
|
||
[16](#iterator-16)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L7685)
|
||
|
||
*Effects*: Equivalent to:if (*outer_it_* == ranges::end(*parent_*->*base_*)) {auto&& inner = *--*outer_it_*; *inner_it_*.template emplace<1>(ranges::end(inner));}while (true) {if (*inner_it_*.index() == 0) {auto& it = std::get<0>(*inner_it_*); if (it == ranges::begin(*parent_*->*pattern_*)) {auto&& inner = *--*outer_it_*; *inner_it_*.template emplace<1>(ranges::end(inner)); } else {break; }} else {auto& it = std::get<1>(*inner_it_*); auto&& inner = **outer_it_*; if (it == ranges::begin(inner)) {*inner_it_*.template emplace<0>(ranges::end(*parent_*->*pattern_*)); } else {break; }}} visit([](auto& it){ --it; }, *inner_it_*);return *this;
|
||
|
||
[ð](#lib:operator--,join_with_view::iterator__)
|
||
|
||
`constexpr iterator operator--(int)
|
||
requires ref-is-glvalue && [bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6 Other range refinements [range.refinements]")<Base> &&
|
||
[bidirectional-common](#concept:bidirectional-common "25.7.15.2 Class template join_with_view [range.join.with.view]")<InnerBase> && [bidirectional-common](#concept:bidirectional-common "25.7.15.2 Class template join_with_view [range.join.with.view]")<PatternBase>;
|
||
`
|
||
|
||
[17](#iterator-17)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L7726)
|
||
|
||
*Effects*: Equivalent to:*iterator* tmp = *this;--*this;return tmp;
|
||
|
||
[ð](#lib:operator==,join_with_view::iterator)
|
||
|
||
`friend constexpr bool operator==(const iterator& x, const iterator& y)
|
||
requires ref-is-glvalue && [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]")<Base> &&
|
||
[equality_comparable](concept.equalitycomparable#concept:equality_comparable "18.5.4 Concept equality_comparable [concept.equalitycomparable]")<InnerIter>;
|
||
`
|
||
|
||
[18](#iterator-18)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L7744)
|
||
|
||
*Effects*: Equivalent to:return x.*outer_it_* == y.*outer_it_* && x.*inner_it_* == y.*inner_it_*;
|
||
|
||
#### [25.7.15.4](#sentinel) Class template join_with_view::*sentinel* [[range.join.with.sentinel]](range.join.with.sentinel)
|
||
|
||
[ð](#lib:join_with_view::sentinel)
|
||
|
||
namespace std::ranges {template<[input_range](range.refinements#concept:input_range "25.4.6 Other range refinements [range.refinements]") V, [forward_range](range.refinements#concept:forward_range "25.4.6 Other range refinements [range.refinements]") Pattern>requires [view](range.view#concept:view "25.4.5 Views [range.view]")<V> && [input_range](range.refinements#concept:input_range "25.4.6 Other range refinements [range.refinements]")<range_reference_t<V>>&& [view](range.view#concept:view "25.4.5 Views [range.view]")<Pattern> && [*concatable*](range.concat.view#concept:concatable "25.7.18.2 Class template concat_view [range.concat.view]")<range_reference_t<V>, Pattern>template<bool Const>class join_with_view<V, Pattern>::*sentinel* {using *Parent* = *maybe-const*<Const, join_with_view>; // *exposition only*using *Base* = *maybe-const*<Const, V>; // *exposition only* sentinel_t<*Base*> *end_* = sentinel_t<*Base*>(); // *exposition only*constexpr explicit *sentinel*(*Parent*& parent); // *exposition only*public:*sentinel*() = default; constexpr *sentinel*(*sentinel*<!Const> s)requires Const && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_to [concept.convertible]")<sentinel_t<V>, sentinel_t<*Base*>>; template<bool OtherConst>requires [sentinel_for](iterator.concept.sentinel#concept:sentinel_for "24.3.4.7 Concept sentinel_for [iterator.concept.sentinel]")<sentinel_t<*Base*>, iterator_t<*maybe-const*<OtherConst, V>>>friend constexpr bool operator==(const *iterator*<OtherConst>& x, const *sentinel*& y); };}
|
||
|
||
[ð](#lib:join_with_view::sentinel,constructor)
|
||
|
||
`constexpr explicit sentinel(Parent& parent);
|
||
`
|
||
|
||
[1](#sentinel-1)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L7786)
|
||
|
||
*Effects*: Initializes *end_* with ranges::end(parent.*base_*)[.](#sentinel-1.sentence-1)
|
||
|
||
[ð](#lib:join_with_view::sentinel,constructor_)
|
||
|
||
`constexpr sentinel(sentinel<!Const> s)
|
||
requires Const && [convertible_to](concept.convertible#concept:convertible_to "18.4.4 Concept convertible_to [concept.convertible]")<sentinel_t<V>, sentinel_t<Base>>;
|
||
`
|
||
|
||
[2](#sentinel-2)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L7798)
|
||
|
||
*Effects*: Initializes *end_* with std::move(s.*end_*)[.](#sentinel-2.sentence-1)
|
||
|
||
[ð](#lib:operator==,join_with_view::sentinel)
|
||
|
||
`template<bool OtherConst>
|
||
requires [sentinel_for](iterator.concept.sentinel#concept:sentinel_for "24.3.4.7 Concept sentinel_for [iterator.concept.sentinel]")<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
|
||
friend constexpr bool operator==(const iterator<OtherConst>& x, const sentinel& y);
|
||
`
|
||
|
||
[3](#sentinel-3)
|
||
|
||
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L7811)
|
||
|
||
*Effects*: Equivalent to: return x.*outer*() == y.*end_*;
|