namespace std::ranges { template<class V> template<bool Const> struct join_view<V>::iterator { private: using Parent = // exposition only conditional_t<Const, const join_view, join_view>; using Base = conditional_t<Const, const V, V>; // exposition only static constexpr bool ref_is_glvalue = // exposition only is_reference_v<iter_reference_t<iterator_t<Base>>>; iterator_t<Base> outer_ = iterator_t<Base>(); // exposition only iterator_t<iter_reference_t<iterator_t<Base>>> inner_ = // exposition only iterator_t<iter_reference_t<iterator_t<Base>>>(); Parent* parent_ = nullptr; // exposition only constexpr void satisfy(); // exposition only public: using iterator_concept = see below; using iterator_category = see below; using value_type = iter_value_t<iterator_t<iter_reference_t<iterator_t<Base>>>>; using difference_type = see below; iterator() = default; constexpr iterator(Parent& parent, iterator_t<V> outer); constexpr iterator(iterator<!Const> i) requires Const && ConvertibleTo<iterator_t<V>, iterator_t<Base>> && ConvertibleTo<iterator_t<InnerRng>, iterator_t<iter_reference_t<iterator_t<Base>>>>; constexpr decltype(auto) operator*() const { return *inner_; } constexpr iterator_t<Base> operator->() const requires has-arrow<iterator_t<Base>>; constexpr iterator& operator++(); constexpr void operator++(int); constexpr iterator operator++(int) requires ref_is_glvalue && ForwardRange<Base> && ForwardRange<iter_reference_t<iterator_t<Base>>>; constexpr iterator& operator--() requires ref_is_glvalue && BidirectionalRange<Base> && BidirectionalRange<iter_reference_t<iterator_t<Base>>>; constexpr iterator operator--(int) requires ref_is_glvalue && BidirectionalRange<Base> && BidirectionalRange<iter_reference_t<iterator_t<Base>>>; friend constexpr bool operator==(const iterator& x, const iterator& y) requires ref_is_glvalue && EqualityComparable<iterator_t<Base>> && EqualityComparable<iterator_t<iter_reference_t<iterator_t<Base>>>>; friend constexpr bool operator!=(const iterator& x, const iterator& y) requires ref_is_glvalue && EqualityComparable<iterator_t<Base>> && EqualityComparable<iterator_t<iter_reference_t<iterator_t<Base>>>>; friend constexpr decltype(auto) iter_move(const iterator& i) noexcept(noexcept(ranges::iter_move(i.inner_))) { return ranges::iter_move(i.inner_); } friend constexpr void iter_swap(const iterator& x, const iterator& y) noexcept(noexcept(ranges::iter_swap(x.inner_, y.inner_))); }; }
common_type_t< iter_difference_t<iterator_t<Base>>, iter_difference_t<iterator_t<iter_reference_t<iterator_t<Base>>>>>
constexpr void satisfy(); // exposition only
auto update_inner = [this](iter_reference_t<iterator_t<Base>> x) -> decltype(auto) { if constexpr (ref_is_glvalue) // x is a reference return (x); // (x) is an lvalue else return (parent_->inner_ = view::all(x)); }; for (; outer_ != ranges::end(parent_->base_); ++outer_) { auto& inner = update_inner(*outer_); inner_ = ranges::begin(inner); if (inner_ != ranges::end(inner)) return; } if constexpr (ref_is_glvalue) inner_ = iterator_t<iter_reference_t<iterator_t<Base>>>();
constexpr iterator(Parent& parent, iterator_t<V> outer)
constexpr iterator(iterator<!Const> i)
requires Const &&
ConvertibleTo<iterator_t<V>, iterator_t<Base>> &&
ConvertibleTo<iterator_t<InnerRng>,
iterator_t<iter_reference_t<iterator_t<Base>>>>;
constexpr iterator_t<Base> operator->() const
requires has-arrow<iterator_t<Base>>;
constexpr iterator& operator++();
auto&& inner_rng = inner-range; if (++inner_ == ranges::end(inner_rng)) { ++outer_; satisfy(); } return *this;
constexpr void operator++(int);
constexpr iterator operator++(int)
requires ref_is_glvalue && ForwardRange<Base> &&
ForwardRange<iter_reference_t<iterator_t<Base>>>;
constexpr iterator& operator--()
requires ref_is_glvalue && BidirectionalRange<Base> &&
BidirectionalRange<iter_reference_t<iterator_t<Base>>>;
if (outer_ == ranges::end(parent_->base_)) inner_ = ranges::end(*--outer_); while (inner_ == ranges::begin(*outer_)) inner_ = ranges::end(*--outer_); --inner_; return *this;
constexpr iterator operator--(int)
requires ref_is_glvalue && BidirectionalRange<Base> &&
BidirectionalRange<iter_reference_t<iterator_t<Base>>>;
friend constexpr bool operator==(const iterator& x, const iterator& y)
requires ref_is_glvalue && EqualityComparable<iterator_t<Base>> &&
EqualityComparable<iterator_t<iter_reference_t<iterator_t<Base>>>>;
friend constexpr bool operator!=(const iterator& x, const iterator& y)
requires ref_is_glvalue && EqualityComparable<iterator_t<Base>> &&
EqualityComparable<iterator_t<iter_reference_t<iterator_t<Base>>>>;
friend constexpr void iter_swap(const iterator& x, const iterator& y)
noexcept(noexcept(ranges::iter_swap(x.inner_, y.inner_)));