Files
2025-10-25 03:02:53 +03:00

29 KiB
Raw Permalink Blame History

[range.concat.iterator]

25 Ranges library [ranges]

25.7 Range adaptors [range.adaptors]

25.7.18 Concat view [range.concat]

25.7.18.3 Class concat_view::iterator [range.concat.iterator]

🔗

namespace std::ranges {template<input_range... Views>requires (view && ...) && (sizeof...(Views) > 0) &&concatable<Views...>templateclass concat_view<Views...>::iterator {public:using iterator_category = see below; // not always presentusing iterator_concept = see below; using value_type = concat-value-t<maybe-const<Const, Views>...>; using difference_type = common_type_t<range_difference_t<maybe-const<Const, Views>>...>; private:using base-iter = // exposition only variant<iterator_t<maybe-const<Const, Views>>...>; maybe-const<Const, concat_view>* parent_ = nullptr; // exposition only**base-iter it_; // exposition onlytemplate<size_t N>constexpr void satisfy(); // exposition onlytemplate<size_t N>constexpr void prev(); // exposition onlytemplate<size_t N>constexpr void advance-fwd(difference_type offset, // exposition only difference_type steps); template<size_t N>constexpr void advance-bwd(difference_type offset, // exposition only difference_type steps); template<class... Args>constexpr explicit iterator(maybe-const<Const, concat_view>* parent, // exposition only Args&&... args)requires constructible_from<base-iter, Args&&...>; public:iterator() = default; constexpr iterator(iterator i)requires Const && (convertible_to<iterator_t, iterator_t> && ...); constexpr decltype(auto) operator*() const; constexpr iterator& operator++(); constexpr void operator++(int); constexpr iterator operator++(int)requires all-forward<Const, Views...>; constexpr iterator& operator--()requires concat-is-bidirectional<Const, Views...>; constexpr iterator operator--(int)requires concat-is-bidirectional<Const, Views...>; constexpr iterator& operator+=(difference_type n)requires concat-is-random-access<Const, Views...>; constexpr iterator& operator-=(difference_type n)requires concat-is-random-access<Const, Views...>; constexpr decltype(auto) operator[](difference_type n) constrequires concat-is-random-access<Const, Views...>; friend constexpr bool operator==(const iterator& x, const iterator& y)requires (equality_comparable<iterator_t<maybe-const<Const, Views>>> && ...); friend constexpr bool operator==(const iterator& it, default_sentinel_t); friend constexpr bool operator<(const iterator& x, const iterator& y)requires all-random-access<Const, Views...>; friend constexpr bool operator>(const iterator& x, const iterator& y)requires all-random-access<Const, Views...>; friend constexpr bool operator<=(const iterator& x, const iterator& y)requires all-random-access<Const, Views...>; friend constexpr bool operator>=(const iterator& x, const iterator& y)requires all-random-access<Const, Views...>; friend constexpr auto operator<=>(const iterator& x, const iterator& y)requires (all-random-access<Const, Views...> &&(three_way_comparable<iterator_t<maybe-const<Const, Views>>> && ...)); friend constexpr iterator operator+(const iterator& it, difference_type n)requires concat-is-random-access<Const, Views...>; friend constexpr iterator operator+(difference_type n, const iterator& it)requires concat-is-random-access<Const, Views...>; friend constexpr iterator operator-(const iterator& it, difference_type n)requires concat-is-random-access<Const, Views...>; friend constexpr difference_type operator-(const iterator& x, const iterator& y)requires concat-is-random-access<Const, Views...>; friend constexpr difference_type operator-(const iterator& x, default_sentinel_t)requires see below; friend constexpr difference_type operator-(default_sentinel_t, const iterator& x)requires see below; friend constexpr decltype(auto) iter_move(const iterator& it) noexcept(see below); friend constexpr void iter_swap(const iterator& x, const iterator& y) noexcept(see below)requires see below; };}

1

#

iterator::iterator_concept is defined as follows:

  • (1.1)

    Ifconcat-is-random-access<Const, Views...> is modeled, then iterator_concept denotes random_access_iterator_tag.

  • (1.2)

    Otherwise, ifconcat-is-bidirectional<Const, Views...> is modeled, then iterator_concept denotes bidirectional_iterator_tag.

  • (1.3)

    Otherwise, ifall-forward<Const, Views...> is modeled, then iterator_concept denotes forward_iterator_tag.

  • (1.4)

    Otherwise, iterator_concept denotes input_iterator_tag.

2

#

The member typedef-name iterator_category is defined if and only ifall-forward<Const, Views...> is modeled.

In that case,iterator::iterator_category is defined as follows:

  • (2.1)

    Ifis_reference_v<concat-reference-t<maybe-const<Const, Views>...>> is false, then iterator_category denotes input_iterator_tag.

  • (2.2)

    Otherwise, let Cs denote the pack of typesiterator_traits<iterator_t<maybe-const<Const, Views>>>::iterator_category....

    • (2.2.1)

      If(derived_from<Cs, random_access_iterator_tag> && ...) && concat-is-random-access<Const, Views...> is true,iterator_category denotes random_access_iterator_tag.

    • (2.2.2)

      Otherwise, if(derived_from<Cs, bidirectional_iterator_tag> && ...) && concat-is-bidirectional<Const, Views...> is true,iterator_category denotes bidirectional_iterator_tag.

    • (2.2.3)

      Otherwise, if(derived_from<Cs, forward_iterator_tag> && ...) is true,iterator_category denotes forward_iterator_tag.

    • (2.2.4)

      Otherwise, iterator_category denotes input_iterator_tag.

🔗

template<size_t N> constexpr void satisfy();

3

#

Effects: Equivalent to:if constexpr (N < (sizeof...(Views) - 1)) {if (std::get(it_) == ranges::end(std::get(parent_->views_))) {it_.template emplace<N + 1>(ranges::begin(std::get<N + 1>(parent_->views_))); satisfy<N + 1>(); }}

🔗

template<size_t N> constexpr void prev();

4

#

Effects: Equivalent to:if constexpr (N == 0) {--std::get<0>(it_);} else {if (std::get(it_) == ranges::begin(std::get(parent_->views_))) {it_.template emplace<N - 1>(ranges::end(std::get<N - 1>(parent_->views_))); prev<N - 1>(); } else {--std::get(it_); }}

🔗

template<size_t N> constexpr void advance-fwd(difference_type offset, difference_type steps);

5

#

Effects: Equivalent to:using underlying_diff_type = iter_difference_t<variant_alternative_t<N, base-iter>>;if constexpr (N == sizeof...(Views) - 1) { std::get(it_) += static_cast<underlying_diff_type>(steps);} else {auto n_size = ranges::distance(std::get(parent_->views_)); if (offset + steps < n_size) { std::get(it_) += static_cast<underlying_diff_type>(steps); } else {it_.template emplace<N + 1>(ranges::begin(std::get<N + 1>(parent_->views_))); advance-fwd<N + 1>(0, offset + steps - n_size); }}

🔗

template<size_t N> constexpr void advance-bwd(difference_type offset, difference_type steps);

6

#

Effects: Equivalent to:using underlying_diff_type = iter_difference_t<variant_alternative_t<N, base-iter>>;if constexpr (N == 0) { std::get(it_) -= static_cast<underlying_diff_type>(steps);} else {if (offset >= steps) { std::get(it_) -= static_cast<underlying_diff_type>(steps); } else {auto prev_size = ranges::distance(std::get<N - 1>(parent_->views_)); it_.template emplace<N - 1>(ranges::end(std::get<N - 1>(parent_->views_))); advance-bwd<N - 1>(prev_size, steps - offset); }}

🔗

template<class... Args> constexpr explicit iterator(maybe-const<Const, concat_view>* parent, Args&&... args) requires [constructible_from](concept.constructible#concept:constructible_from "18.4.11Concept constructible_­from[concept.constructible]")<base-iter, Args&&...>;

7

#

Effects: Initializes parent_ with parent, and initializes it_ with std::forward(args)....

🔗

constexpr iterator(iterator<!Const> it) requires Const && ([convertible_to](concept.convertible#concept:convertible_to "18.4.4Concept convertible_­to[concept.convertible]")<iterator_t<Views>, iterator_t<const Views>> && ...);

8

#

Preconditions: it.it_.valueless_by_exception() is false.

9

#

Effects: Initializes parent_ with it.parent_, and let i be it.it_.index(), initializes it_ withbase-iter(in_place_index, std::get(std::move(it.it_))).

🔗

constexpr decltype(auto) operator*() const;

10

#

Preconditions: it_.valueless_by_exception() is false.

11

#

Effects: Equivalent to:using reference = concat-reference-t<maybe-const<Const, Views>...>;return std::visit([](auto&& it) -> reference { return *it; }, it_);

🔗

constexpr iterator& operator++();

12

#

Preconditions: it_.valueless_by_exception() is false.

13

#

Effects: Let i be it_.index().

Equivalent to:++std::get(it_);satisfy();return *this;

🔗

constexpr void operator++(int);

14

#

Effects: Equivalent to:++*this;

🔗

constexpr iterator operator++(int) requires [all-forward](range.adaptor.helpers#concept:all-forward "25.7.5Range adaptor helpers[range.adaptor.helpers]")<Const, Views...>;

15

#

Effects: Equivalent to:auto tmp = *this;++*this;return tmp;

🔗

constexpr iterator& operator--() requires [concat-is-bidirectional](range.concat.view#concept:concat-is-bidirectional "25.7.18.2Class template concat_­view[range.concat.view]")<Const, Views...>;

16

#

Preconditions: it_.valueless_by_exception() is false.

17

#

Effects: Let i be it_.index().

Equivalent to:prev();return *this;

🔗

constexpr iterator operator--(int) requires [concat-is-bidirectional](range.concat.view#concept:concat-is-bidirectional "25.7.18.2Class template concat_­view[range.concat.view]")<Const, Views...>;

18

#

Effects: Equivalent to:auto tmp = *this;--*this;return tmp;

🔗

constexpr iterator& operator+=(difference_type n) requires [concat-is-random-access](range.concat.view#concept:concat-is-random-access "25.7.18.2Class template concat_­view[range.concat.view]")<Const, Views...>;

19

#

Preconditions: it_.valueless_by_exception() is false.

20

#

Effects: Let i be it_.index().

Equivalent to:if (n > 0) {advance-fwd(std::get(it_) - ranges::begin(std::get(parent_->views_)), n);} else if (n < 0) {advance-bwd(std::get(it_) - ranges::begin(std::get(parent_->views_)), -n);}return *this;

🔗

constexpr iterator& operator-=(difference_type n) requires [concat-is-random-access](range.concat.view#concept:concat-is-random-access "25.7.18.2Class template concat_­view[range.concat.view]")<Const, Views...>;

21

#

Effects: Equivalent to:*this += -n;return *this;

🔗

constexpr decltype(auto) operator[](difference_type n) const requires [concat-is-random-access](range.concat.view#concept:concat-is-random-access "25.7.18.2Class template concat_­view[range.concat.view]")<Const, Views...>;

22

#

Effects: Equivalent to:return *((*this) + n);

🔗

friend constexpr bool operator==(const iterator& x, const iterator& y) requires ([equality_comparable](concept.equalitycomparable#concept:equality_comparable "18.5.4Concept equality_­comparable[concept.equalitycomparable]")<iterator_t<maybe-const<Const, Views>>> && ...);

23

#

Preconditions: x.it_.valueless_by_exception() andy.it_.valueless_by_exception() are each false.

24

#

Effects: Equivalent to:return x.it_ == y.it_;

🔗

friend constexpr bool operator==(const iterator& it, default_sentinel_t);

25

#

Preconditions: it.it_.valueless_by_exception() is false.

26

#

Effects: Equivalent to:constexpr auto last_idx = sizeof...(Views) - 1;return it.it_.index() == last_idx && std::get<last_idx>(it.it_) == ranges::end(std::get<last_idx>(it.parent_->views_));

🔗

friend constexpr bool operator<(const iterator& x, const iterator& y) requires [all-random-access](range.adaptor.helpers#concept:all-random-access "25.7.5Range adaptor helpers[range.adaptor.helpers]")<Const, Views...>; friend constexpr bool operator>(const iterator& x, const iterator& y) requires [all-random-access](range.adaptor.helpers#concept:all-random-access "25.7.5Range adaptor helpers[range.adaptor.helpers]")<Const, Views...>; friend constexpr bool operator<=(const iterator& x, const iterator& y) requires [all-random-access](range.adaptor.helpers#concept:all-random-access "25.7.5Range adaptor helpers[range.adaptor.helpers]")<Const, Views...>; friend constexpr bool operator>=(const iterator& x, const iterator& y) requires [all-random-access](range.adaptor.helpers#concept:all-random-access "25.7.5Range adaptor helpers[range.adaptor.helpers]")<Const, Views...>; friend constexpr auto operator<=>(const iterator& x, const iterator& y) requires ([all-random-access](range.adaptor.helpers#concept:all-random-access "25.7.5Range adaptor helpers[range.adaptor.helpers]")<Const, Views...> && ([three_way_comparable](cmp.concept#concept:three_way_comparable "17.12.4Concept three_­way_­comparable[cmp.concept]")<iterator_t<maybe-const<Const, Views>>> && ...));

27

#

Preconditions: x.it_.valueless_by_exception() andy.it_.valueless_by_exception() are each false.

28

#

Let op be the operator.

29

#

Effects: Equivalent to:return x.it_ op y.it_;

🔗

friend constexpr iterator operator+(const iterator& it, difference_type n) requires [concat-is-random-access](range.concat.view#concept:concat-is-random-access "25.7.18.2Class template concat_­view[range.concat.view]")<Const, Views...>;

30

#

Effects: Equivalent to:auto temp = it; temp += n;return temp;

🔗

friend constexpr iterator operator+(difference_type n, const iterator& it) requires [concat-is-random-access](range.concat.view#concept:concat-is-random-access "25.7.18.2Class template concat_­view[range.concat.view]")<Const, Views...>;

31

#

Effects: Equivalent to:return it + n;

🔗

friend constexpr iterator operator-(const iterator& it, difference_type n) requires [concat-is-random-access](range.concat.view#concept:concat-is-random-access "25.7.18.2Class template concat_­view[range.concat.view]")<Const, Views...>;

32

#

Effects: Equivalent to:auto temp = it; temp -= n;return temp;

🔗

friend constexpr difference_type operator-(const iterator& x, const iterator& y) requires [concat-is-random-access](range.concat.view#concept:concat-is-random-access "25.7.18.2Class template concat_­view[range.concat.view]")<Const, Views...>;

33

#

Preconditions: x.it_.valueless_by_exception() andy.it_.valueless_by_exception() are each false.

34

#

Effects: Letix denote x.it_.index() andiy denote y.it_.index().

If ix > iy, letdy beranges::distance(std::get(y.it_), ranges::end(std::get(y.parent_->views_))),dx beranges::distance(ranges::begin(std::get(x.parent_->views_)), std::get(x.it_)). Let s denote the sum of the sizes of all the rangesstd::get(x.parent_->views_) for every integer i in the range [iy + 1, ix) if there is any, and0 otherwise, of type difference_type, equivalent to:return dy + s + dx;

otherwise, if ix < iy is true, equivalent to:return -(y - x);

otherwise, equivalent to:return std::get(x.it_) - std::get(y.it_);

🔗

friend constexpr difference_type operator-(const iterator& x, default_sentinel_t) requires see below;

35

#

Preconditions: x.it_.valueless_by_exception() is false.

36

#

Effects: Letix denote x.it_.index(),dx beranges::distance(std::get(x.it_), ranges::end(std::get(x.parent_->views_))).

Let s denote the sum of the sizes of all the rangesstd::get(x.parent_->views_) for every integer i in the range [ix + 1, sizeof...(Views)) if there is any, and0 otherwise, of type difference_type, equivalent to:return -(dx + s);

37

#

Remarks: Let Fs be the pack that consists of all elements of Views except the first element, the expression in the requires-clause is equivalent to:(sized_sentinel_for<sentinel_t<maybe-const<Const, Views>>, iterator_t<maybe-const<Const, Views>>> && ...) &&(sized_range<maybe-const<Const, Fs>> && ...)

🔗

friend constexpr difference_type operator-(default_sentinel_t, const iterator& x) requires see below;

38

#

Effects: Equivalent to:return -(x - default_sentinel);

39

#

Remarks: Let Fs be the pack that consists of all elements of Views except the first element, the expression in the requires-clause is equivalent to:(sized_sentinel_for<sentinel_t<maybe-const<Const, Views>>, iterator_t<maybe-const<Const, Views>>> && ...) &&(sized_range<maybe-const<Const, Fs>> && ...)

🔗

friend constexpr decltype(auto) iter_move(const iterator& it) noexcept(see below);

40

#

Preconditions: it.it_.valueless_by_exception() is false.

41

#

Effects: Equivalent to:return std::visit([](const auto& i)-> concat-rvalue-reference-t<maybe-const<Const, Views>...> {return ranges::iter_move(i); }, it.it_);

42

#

Remarks: The exception specification is equivalent to:((is_nothrow_invocable_v<decltype(ranges::iter_move), const iterator_t<maybe-const<Const, Views>>&> && is_nothrow_convertible_v<range_rvalue_reference_t<maybe-const<Const, Views>>, concat-rvalue-reference-t<maybe-const<Const, Views>...>>) &&...)

🔗

friend constexpr void iter_swap(const iterator& x, const iterator& y) noexcept(see below) requires see below;

43

#

Preconditions: x.it_.valueless_by_exception() andy.it_.valueless_by_exception() are each false.

44

#

Effects: Equivalent to:std::visit([&](const auto& it1, const auto& it2) {if constexpr (is_same_v<decltype(it1), decltype(it2)>) { ranges::iter_swap(it1, it2); } else { ranges::swap(*x, *y); }}, x.it_, y.it_);

45

#

Remarks: The exception specification is equivalent to(noexcept(ranges::swap(*x, *y)) && ... && noexcept(ranges::iter_swap(its, its))) where its is a pack of lvalues of typeconst iterator_t<maybe-const<Const, Views>> respectively.

The expression in the requires-clause is equivalent toswappable_with<iter_reference_t<iterator>, iter_reference_t<iterator>> &&(... && indirectly_swappable<iterator_t<maybe-const<Const, Views>>>)