[range.cartesian.iterator] (original) (raw)
25 Ranges library [ranges]
25.7 Range adaptors [range.adaptors]
25.7.33 Cartesian product view [range.cartesian]
25.7.33.3 Class template cartesian_product_view::iterator [range.cartesian.iterator]
namespace std::ranges { template<input_range First, forward_range... Vs> requires (view<First> && ... && view<Vs>) template<bool Const> class cartesian_product_view<First, Vs...>::iterator { public: using iterator_category = input_iterator_tag;using iterator_concept = see below;using value_type = tuple<range_value_t<_maybe-const_<Const, First>>, range_value_t<_maybe-const_<Const, Vs>>...>;using reference = tuple<range_reference_t<_maybe-const_<Const, First>>, range_reference_t<_maybe-const_<Const, Vs>>...>;using difference_type = see below;iterator() = default;constexpr iterator(iterator<!Const> i) requires Const && (convertible_to<iterator_t<First>, iterator_t<const First>> && ... && convertible_to<iterator_t<Vs>, iterator_t<const Vs>>);constexpr auto operator*() const;constexpr iterator& operator++();constexpr void operator++(int);constexpr iterator operator++(int) requires forward_range<_maybe-const_<Const, First>>;constexpr iterator& operator--() requires cartesian-product-is-bidirectional<Const, First, Vs...>;constexpr iterator operator--(int) requires cartesian-product-is-bidirectional<Const, First, Vs...>;constexpr iterator& operator+=(difference_type x) requires cartesian-product-is-random-access<Const, First, Vs...>;constexpr iterator& operator-=(difference_type x) requires cartesian-product-is-random-access<Const, First, Vs...>;constexpr reference operator[](difference_type n) const requires cartesian-product-is-random-access<Const, First, Vs...>;friend constexpr bool operator==(const iterator& x, const iterator& y) requires equality_comparable<iterator_t<_maybe-const_<Const, First>>>;friend constexpr bool operator==(const iterator& x, default_sentinel_t);friend constexpr auto operator<=>(const iterator& x, const iterator& y) requires all-random-access<Const, First, Vs...>;friend constexpr iterator operator+(const iterator& x, difference_type y) requires cartesian-product-is-random-access<Const, First, Vs...>;friend constexpr iterator operator+(difference_type x, const iterator& y) requires cartesian-product-is-random-access<Const, First, Vs...>;friend constexpr iterator operator-(const iterator& x, difference_type y) requires cartesian-product-is-random-access<Const, First, Vs...>;friend constexpr difference_type operator-(const iterator& x, const iterator& y) requires cartesian-is-sized-sentinel<Const, iterator_t, First, Vs...>;friend constexpr difference_type operator-(const iterator& i, default_sentinel_t) requires cartesian-is-sized-sentinel<Const, sentinel_t, First, Vs...>;friend constexpr difference_type operator-(default_sentinel_t, const iterator& i) requires cartesian-is-sized-sentinel<Const, sentinel_t, First, Vs...>;friend constexpr auto iter_move(const iterator& i) noexcept(see below);friend constexpr void iter_swap(const iterator& l, const iterator& r) noexcept(see below) requires (indirectly_swappable<iterator_t<_maybe-const_<Const, First>>> && ... && indirectly_swappable<iterator_t<_maybe-const_<Const, Vs>>>);private: using Parent = maybe-const<Const, cartesian_product_view>; Parent* parent_ = nullptr; tuple<iterator_t<_maybe-const_<Const, First>>, iterator_t<_maybe-const_<Const, Vs>>...> current_; template<size_t N = sizeof...(Vs)> constexpr void next(); template<size_t N = sizeof...(Vs)> constexpr void prev(); template<class Tuple> constexpr difference_type distance-from(const Tuple& t) const; constexpr iterator(Parent& parent, tuple<iterator_t<_maybe-const_<Const, First>>, iterator_t<_maybe-const_<Const, Vs>>...> current); };}
_iterator_::iterator_concept is defined as follows:
- Otherwise, if maybe-const<Const, First> models forward_range, then iterator_concept denotes forward_iterator_tag.
- Otherwise, iterator_concept denotes input_iterator_tag.
_iterator_::difference_type is an implementation-defined signed-integer-like type.
Recommended practice: _iterator_::difference_type should be the smallest signed-integer-like type that is sufficiently wide to store the product of the maximum sizes of all underlying ranges if such a type exists.
template<size_t N = sizeof...(Vs)> constexpr void _next_();
Effects: Equivalent to:auto& it = std::get<N>(current_);++it;if constexpr (N > 0) { if (it == ranges::end(std::get<N>(_parent__->bases_))) { it = ranges::begin(std::get<N>(_parent__->bases_));next<N - 1>();} }
template<size_t N = sizeof...(Vs)> constexpr void _prev_();
Effects: Equivalent to:auto& it = std::get<N>(current_);if constexpr (N > 0) { if (it == ranges::begin(std::get<N>(_parent__->bases_))) { it = cartesian-common-arg-end(std::get<N>(_parent__->bases_));prev<N - 1>();} } --it;
template<class Tuple> constexpr difference_type _distance-from_(const Tuple& t) const;
Let:
- scaled-size(N) be the product ofstatic_cast<difference_type>(ranges::size(std::get<N>(_parent__->bases_))) andif N ≤ sizeof...(Vs), otherwise static_cast<difference_type>(1);
- scaled-distance(N) be the product ofstatic_cast<difference_type>(std::get<N>(current_) - std::get<N>(t)) and ; and
- scaled-sum be the sum of scaled-distance(N)for every integer 0 ≤ N ≤ sizeof...(Vs).
Preconditions: scaled-sum can be represented by difference_type.
constexpr _iterator_(_Parent_& parent, tuple<iterator_t<_maybe-const_<Const, First>>, iterator_t<_maybe-const_<Const, Vs>>...> current);
Effects: Initializes_parent__ with addressof(parent) and_current__ with std::move(current).
constexpr _iterator_(_iterator_<!Const> i) requires Const && ([convertible_to](concept.convertible#concept:convertible%5Fto "18.4.4 Concept convertible_to [concept.convertible]")<iterator_t<First>, iterator_t<const First>> && ... && [convertible_to](concept.convertible#concept:convertible%5Fto "18.4.4 Concept convertible_to [concept.convertible]")<iterator_t<Vs>, iterator_t<const Vs>>);
Effects: Initializes_parent__ with i.parent_ and_current__ with std::move(i.current_).
constexpr auto operator*() const;
Effects: Equivalent to:return tuple-transform([](auto& i) -> decltype(auto) { return *i; }, current_);
constexpr _iterator_& operator++();
Effects: Equivalent to:next();return *this;
constexpr void operator++(int);
Effects: Equivalent to ++*this.
constexpr _iterator_ operator++(int) requires [forward_range](range.refinements#concept:forward%5Frange "25.4.6 Other range refinements [range.refinements]")<_maybe-const_<Const, First>>;
Effects: Equivalent to:auto tmp = *this;++*this;return tmp;
Effects: Equivalent to:prev();return *this;
Effects: Equivalent to:auto tmp = *this;--*this;return tmp;
Let orig be the value of *this before the call.
Let ret be:
- If x > 0, the value of *this had next been called x times.
- Otherwise, if x < 0, the value of *this had prev been called -x times.
Preconditions: x is in the range[ranges::distance(*this, ranges::begin(*parent_)),
ranges::distance(*this, ranges::end(*parent_))].
Effects: Sets the value of *this to ret.
Effects: Equivalent to:*this += -x;return *this;
Effects: Equivalent to: return *((*this) + n);
friend constexpr bool operator==(const _iterator_& x, const _iterator_& y) requires [equality_comparable](concept.equalitycomparable#concept:equality%5Fcomparable "18.5.4 Concept equality_comparable [concept.equalitycomparable]")<iterator_t<_maybe-const_<Const, First>>>;
Effects: Equivalent to: return x.current_ == y.current_;
friend constexpr bool operator==(const _iterator_& x, default_sentinel_t);
Returns: true if std::get<i>(x.current_) == ranges::end(std::get<i>(x._parent__->bases_))is truefor any integer 0 ≤ i ≤ sizeof...(Vs); otherwise, false.
friend constexpr auto operator<=>(const _iterator_& x, const _iterator_& y) requires [_all-random-access_](range.adaptor.helpers#concept:all-random-access "25.7.5 Range adaptor helpers [range.adaptor.helpers]")<Const, First, Vs...>;
Effects: Equivalent to: return x.current_ <=> y.current_;
Effects: Equivalent to: return iterator(x) += y;
Effects: Equivalent to: return y + x;
Effects: Equivalent to: return iterator(x) -= y;
friend constexpr difference_type operator-(const _iterator_& x, const _iterator_& y) requires [_cartesian-is-sized-sentinel_](range.cartesian.view#concept:cartesian-is-sized-sentinel "25.7.33.2 Class template cartesian_product_view [range.cartesian.view]")<Const, iterator_t, First, Vs...>;
Effects: Equivalent to: return x.distance-from(y.current_);
friend constexpr difference_type operator-(const _iterator_& i, default_sentinel_t) requires [_cartesian-is-sized-sentinel_](range.cartesian.view#concept:cartesian-is-sized-sentinel "25.7.33.2 Class template cartesian_product_view [range.cartesian.view]")<Const, sentinel_t, First, Vs...>;
Let end-tuple be an object of a type that is a specialization of tuple, such that:
- std::get<0>(end-tuple) has the same value asranges::end(std::get<0>(i._parent__->bases_));
- std::get<N>(end-tuple) has the same value asranges::begin(std::get<N>(i._parent__->bases_))for every integer 1 ≤ N ≤ sizeof...(Vs).
Effects: Equivalent to: return i.distance-from(end-tuple);
friend constexpr difference_type operator-(default_sentinel_t s, const _iterator_& i) requires [_cartesian-is-sized-sentinel_](range.cartesian.view#concept:cartesian-is-sized-sentinel "25.7.33.2 Class template cartesian_product_view [range.cartesian.view]")<Const, sentinel_t, First, Vs...>;
Effects: Equivalent to: return -(i - s);
friend constexpr auto iter_move(const _iterator_& i) noexcept(_see below_);
Effects: Equivalent to: return tuple-transform(ranges::iter_move, i.current_);
Remarks: The exception specification is equivalent to the logical and of the following expressions:
- noexcept(ranges::iter_move(std::get<N>(i.current_)))for every integer
0 ≤ N ≤ sizeof...(Vs), - is_nothrow_move_constructible_v<range_rvalue_reference_t<_maybe-const_<Const, T>>>
for every type T in First, Vs....
friend constexpr void iter_swap(const _iterator_& l, const _iterator_& r) noexcept(_see below_) requires ([indirectly_swappable](alg.req.ind.swap#concept:indirectly%5Fswappable "24.3.7.4 Concept indirectly_swappable [alg.req.ind.swap]")<iterator_t<_maybe-const_<Const, First>>> && ... && [indirectly_swappable](alg.req.ind.swap#concept:indirectly%5Fswappable "24.3.7.4 Concept indirectly_swappable [alg.req.ind.swap]")<iterator_t<_maybe-const_<Const, Vs>>>);
Effects: For every integer 0 ≤ i ≤ sizeof...(Vs), performs:ranges::iter_swap(std::get<i>(l.current_), std::get<i>(r.current_))
Remarks: The exception specification is equivalent to the logical and of the following expressions:
- noexcept(ranges::iter_swap(std::get<i>(l.current_), std::get<i>(r.current_)))for
every integer 0 ≤ i ≤ sizeof...(Vs).