Files
cppdraft_translate/cppdraft/iterators/common.md
2025-10-25 03:02:53 +03:00

366 lines
22 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

[iterators.common]
# 24 Iterators library [[iterators]](./#iterators)
## 24.5 Iterator adaptors [[predef.iterators]](predef.iterators#iterators.common)
### 24.5.5 Common iterators [iterators.common]
#### [24.5.5.1](#common.iterator) Class template common_iterator [[common.iterator]](common.iterator)
[1](#common.iterator-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iterators.tex#L5414)
Class template common_iterator is an iterator/sentinel adaptor that is
capable of representing a non-common range of elements (where the types of the
iterator and sentinel differ) as a common range (where they are the same)[.](#common.iterator-1.sentence-1)
It
does this by holding either an iterator or a sentinel, and implementing the
equality comparison operators appropriately[.](#common.iterator-1.sentence-2)
[2](#common.iterator-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iterators.tex#L5421)
[*Note [1](#common.iterator-note-1)*:
The common_iterator type is useful for interfacing with legacy
code that expects the begin and end of a range to have the same type[.](#common.iterator-2.sentence-1)
— *end note*]
[3](#common.iterator-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iterators.tex#L5427)
[*Example [1](#common.iterator-example-1)*: template<class ForwardIterator>void fun(ForwardIterator begin, ForwardIterator end);
list<int> s;// populate the list susing CI = common_iterator<counted_iterator<list<int>::iterator>, default_sentinel_t>;// call fun on a range of 10 ints fun(CI(counted_iterator(s.begin(), 10)), CI(default_sentinel)); — *end example*]
[🔗](#lib:common_iterator)
namespace std {template<[input_or_output_iterator](iterator.concept.iterator#concept:input_or_output_iterator "24.3.4.6Concept input_­or_­output_­iterator[iterator.concept.iterator]") I, [sentinel_for](iterator.concept.sentinel#concept:sentinel_for "24.3.4.7Concept sentinel_­for[iterator.concept.sentinel]")<I> S>requires (![same_as](concept.same#concept:same_as "18.4.2Concept same_­as[concept.same]")<I, S> && [copyable](concepts.object#concept:copyable "18.6Object concepts[concepts.object]")<I>)class common_iterator {public:constexpr common_iterator() requires [default_initializable](concept.default.init#concept:default_initializable "18.4.12Concept default_­initializable[concept.default.init]")<I> = default; constexpr common_iterator(I i); constexpr common_iterator(S s); template<class I2, class S2>requires [convertible_to](concept.convertible#concept:convertible_to "18.4.4Concept convertible_­to[concept.convertible]")<const I2&, I> && [convertible_to](concept.convertible#concept:convertible_to "18.4.4Concept convertible_­to[concept.convertible]")<const S2&, S>constexpr common_iterator(const common_iterator<I2, S2>& x); template<class I2, class S2>requires [convertible_to](concept.convertible#concept:convertible_to "18.4.4Concept convertible_­to[concept.convertible]")<const I2&, I> && [convertible_to](concept.convertible#concept:convertible_to "18.4.4Concept convertible_­to[concept.convertible]")<const S2&, S> &&[assignable_from](concept.assignable#concept:assignable_from "18.4.8Concept assignable_­from[concept.assignable]")<I&, const I2&> && [assignable_from](concept.assignable#concept:assignable_from "18.4.8Concept assignable_­from[concept.assignable]")<S&, const S2&>constexpr common_iterator& operator=(const common_iterator<I2, S2>& x); constexpr decltype(auto) operator*(); constexpr decltype(auto) operator*() constrequires [*dereferenceable*](iterator.synopsis#concept:dereferenceable "24.2Header <iterator>&nbsp;synopsis[iterator.synopsis]")<const I>; constexpr auto operator->() constrequires *see below*; constexpr common_iterator& operator++(); constexpr decltype(auto) operator++(int); template<class I2, [sentinel_for](iterator.concept.sentinel#concept:sentinel_for "24.3.4.7Concept sentinel_­for[iterator.concept.sentinel]")<I> S2>requires [sentinel_for](iterator.concept.sentinel#concept:sentinel_for "24.3.4.7Concept sentinel_­for[iterator.concept.sentinel]")<S, I2>friend constexpr bool operator==(const common_iterator& x, const common_iterator<I2, S2>& y); template<class I2, [sentinel_for](iterator.concept.sentinel#concept:sentinel_for "24.3.4.7Concept sentinel_­for[iterator.concept.sentinel]")<I> S2>requires [sentinel_for](iterator.concept.sentinel#concept:sentinel_for "24.3.4.7Concept sentinel_­for[iterator.concept.sentinel]")<S, I2> && [equality_comparable_with](concept.equalitycomparable#concept:equality_comparable_with "18.5.4Concept equality_­comparable[concept.equalitycomparable]")<I, I2>friend constexpr bool operator==(const common_iterator& x, const common_iterator<I2, S2>& y); template<[sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8Concept sized_­sentinel_­for[iterator.concept.sizedsentinel]")<I> I2, [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8Concept sized_­sentinel_­for[iterator.concept.sizedsentinel]")<I> S2>requires [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8Concept sized_­sentinel_­for[iterator.concept.sizedsentinel]")<S, I2>friend constexpr iter_difference_t<I2> operator-(const common_iterator& x, const common_iterator<I2, S2>& y); friend constexpr decltype(auto) iter_move(const common_iterator& i)noexcept(noexcept(ranges::iter_move(declval<const I&>())))requires [input_iterator](iterator.concept.input#concept:input_iterator "24.3.4.9Concept input_­iterator[iterator.concept.input]")<I>; template<[indirectly_swappable](alg.req.ind.swap#concept:indirectly_swappable "24.3.7.4Concept indirectly_­swappable[alg.req.ind.swap]")<I> I2, class S2>friend constexpr void iter_swap(const common_iterator& x, const common_iterator<I2, S2>& y)noexcept(noexcept(ranges::iter_swap(declval<const I&>(), declval<const I2&>()))); private: variant<I, S> v_; // *exposition only*}; template<class I, class S>struct incrementable_traits<common_iterator<I, S>> {using difference_type = iter_difference_t<I>; }; template<[input_iterator](iterator.concept.input#concept:input_iterator "24.3.4.9Concept input_­iterator[iterator.concept.input]") I, class S>struct iterator_traits<common_iterator<I, S>> {using iterator_concept = *see below*; using iterator_category = *see below*; // not always presentusing value_type = iter_value_t<I>; using difference_type = iter_difference_t<I>; using pointer = *see below*; using reference = iter_reference_t<I>; };}
#### [24.5.5.2](#common.iter.types) Associated types [[common.iter.types]](common.iter.types)
[1](#common.iter.types-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iterators.tex#L5513)
The nested [*typedef-name*](dcl.typedef#nt:typedef-name "9.2.4The typedef specifier[dcl.typedef]") iterator_category of
the specialization of iterator_traits for common_iterator<I, S> is defined if and only if iter_difference_t<I> is an integral type[.](#common.iter.types-1.sentence-1)
In that case,iterator_category denotes forward_iterator_tag if
the [*qualified-id*](expr.prim.id.qual#nt:qualified-id "7.5.5.3Qualified names[expr.prim.id.qual]") iterator_traits<I>::iterator_category is valid and denotes a type that
models [derived_from](concept.derived#concept:derived_from "18.4.3Concept derived_­from[concept.derived]")<forward_iterator_tag>;
otherwise it denotes input_iterator_tag[.](#common.iter.types-1.sentence-2)
[2](#common.iter.types-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iterators.tex#L5524)
The remaining nested [*typedef-name*](dcl.typedef#nt:typedef-name "9.2.4The typedef specifier[dcl.typedef]")*s* of the specialization ofiterator_traits for common_iterator<I, S> are defined as follows:
- [(2.1)](#common.iter.types-2.1)
iterator_concept denotes forward_iterator_tag if I models [forward_iterator](iterator.concept.forward#concept:forward_iterator "24.3.4.11Concept forward_­iterator[iterator.concept.forward]");
otherwise it denotes input_iterator_tag[.](#common.iter.types-2.1.sentence-1)
- [(2.2)](#common.iter.types-2.2)
Let a denote an lvalue of type const common_iterator<I, S>[.](#common.iter.types-2.2.sentence-1)
If the expression a.operator->() is well-formed,
then pointer denotes decltype(a.operator->())[.](#common.iter.types-2.2.sentence-2)
Otherwise, pointer denotes void[.](#common.iter.types-2.2.sentence-3)
#### [24.5.5.3](#common.iter.const) Constructors and conversions [[common.iter.const]](common.iter.const)
[🔗](#lib:common_iterator,constructor)
`constexpr common_iterator(I i);
`
[1](#common.iter.const-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iterators.tex#L5548)
*Effects*: Initializes v_ as if by v_{in_place_type<I>, std::move(i)}[.](#common.iter.const-1.sentence-1)
[🔗](#lib:common_iterator,constructor_)
`constexpr common_iterator(S s);
`
[2](#common.iter.const-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iterators.tex#L5559)
*Effects*: Initializes v_ as if byv_{in_place_type<S>, std::move(s)}[.](#common.iter.const-2.sentence-1)
[🔗](#lib:common_iterator,constructor__)
`template<class I2, class S2>
requires [convertible_to](concept.convertible#concept:convertible_to "18.4.4Concept convertible_­to[concept.convertible]")<const I2&, I> && [convertible_to](concept.convertible#concept:convertible_to "18.4.4Concept convertible_­to[concept.convertible]")<const S2&, S>
constexpr common_iterator(const common_iterator<I2, S2>& x);
`
[3](#common.iter.const-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iterators.tex#L5573)
*Hardened preconditions*: x.v_.valueless_by_exception() is false[.](#common.iter.const-3.sentence-1)
[4](#common.iter.const-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iterators.tex#L5577)
*Effects*: Initializes v_ as if byv_{in_place_index<i>, get<i>(x.v_)},
where i is x.v_.index()[.](#common.iter.const-4.sentence-1)
[🔗](#lib:operator=,common_iterator)
`template<class I2, class S2>
requires [convertible_to](concept.convertible#concept:convertible_to "18.4.4Concept convertible_­to[concept.convertible]")<const I2&, I> && [convertible_to](concept.convertible#concept:convertible_to "18.4.4Concept convertible_­to[concept.convertible]")<const S2&, S> &&
[assignable_from](concept.assignable#concept:assignable_from "18.4.8Concept assignable_­from[concept.assignable]")<I&, const I2&> && [assignable_from](concept.assignable#concept:assignable_from "18.4.8Concept assignable_­from[concept.assignable]")<S&, const S2&>
constexpr common_iterator& operator=(const common_iterator<I2, S2>& x);
`
[5](#common.iter.const-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iterators.tex#L5593)
*Hardened preconditions*: x.v_.valueless_by_exception() is false[.](#common.iter.const-5.sentence-1)
[6](#common.iter.const-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iterators.tex#L5597)
*Effects*: Equivalent to:
- [(6.1)](#common.iter.const-6.1)
If v_.index() == x.v_.index(), thenget<i>(v_) = get<i>(x.v_)[.](#common.iter.const-6.1.sentence-1)
- [(6.2)](#common.iter.const-6.2)
Otherwise, v_.emplace<i>(get<i>(x.v_))[.](#common.iter.const-6.2.sentence-1)
where i is x.v_.index()[.](#common.iter.const-6.sentence-2)
[7](#common.iter.const-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iterators.tex#L5608)
*Returns*: *this[.](#common.iter.const-7.sentence-1)
#### [24.5.5.4](#common.iter.access) Accessors [[common.iter.access]](common.iter.access)
[🔗](#lib:operator*,common_iterator)
`constexpr decltype(auto) operator*();
constexpr decltype(auto) operator*() const
requires [dereferenceable](iterator.synopsis#concept:dereferenceable "24.2Header <iterator>&nbsp;synopsis[iterator.synopsis]")<const I>;
`
[1](#common.iter.access-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iterators.tex#L5623)
*Hardened preconditions*: holds_alternative<I>(v_) is true[.](#common.iter.access-1.sentence-1)
[2](#common.iter.access-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iterators.tex#L5627)
*Effects*: Equivalent to: return *get<I>(v_);
[🔗](#lib:operator-%3e,common_iterator)
`constexpr auto operator->() const
requires see below;
`
[3](#common.iter.access-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iterators.tex#L5639)
The expression in the [*requires-clause*](temp.pre#nt:requires-clause "13.1Preamble[temp.pre]") is equivalent to:[indirectly_readable](iterator.concept.readable#concept:indirectly_readable "24.3.4.2Concept indirectly_­readable[iterator.concept.readable]")<const I> &&(requires(const I& i) { i.operator->(); } || is_reference_v<iter_reference_t<I>> ||[constructible_from](concept.constructible#concept:constructible_from "18.4.11Concept constructible_­from[concept.constructible]")<iter_value_t<I>, iter_reference_t<I>>)
[4](#common.iter.access-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iterators.tex#L5648)
*Hardened preconditions*: holds_alternative<I>(v_) is true[.](#common.iter.access-4.sentence-1)
[5](#common.iter.access-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iterators.tex#L5652)
*Effects*:
- [(5.1)](#common.iter.access-5.1)
If I is a pointer type or if the expressionget<I>(v_).operator->() is
well-formed, equivalent to: return get<I>(v_);
- [(5.2)](#common.iter.access-5.2)
Otherwise, if iter_reference_t<I> is a reference type, equivalent to:auto&& tmp = *get<I>(v_);return addressof(tmp);
- [(5.3)](#common.iter.access-5.3)
Otherwise, equivalent to:return *proxy*(*get<I>(v_)); where*proxy* is the exposition-only class:class *proxy* { iter_value_t<I> keep_; constexpr *proxy*(iter_reference_t<I>&& x): keep_(std::move(x)) {}public:constexpr const iter_value_t<I>* operator->() const noexcept {return addressof(keep_); }};
#### [24.5.5.5](#common.iter.nav) Navigation [[common.iter.nav]](common.iter.nav)
[🔗](#lib:operator++,common_iterator)
`constexpr common_iterator& operator++();
`
[1](#common.iter.nav-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iterators.tex#L5693)
*Hardened preconditions*: holds_alternative<I>(v_) is true[.](#common.iter.nav-1.sentence-1)
[2](#common.iter.nav-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iterators.tex#L5697)
*Effects*: Equivalent to ++get<I>(v_)[.](#common.iter.nav-2.sentence-1)
[3](#common.iter.nav-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iterators.tex#L5701)
*Returns*: *this[.](#common.iter.nav-3.sentence-1)
[🔗](#lib:operator++,common_iterator_)
`constexpr decltype(auto) operator++(int);
`
[4](#common.iter.nav-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iterators.tex#L5712)
*Hardened preconditions*: holds_alternative<I>(v_) is true[.](#common.iter.nav-4.sentence-1)
[5](#common.iter.nav-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iterators.tex#L5716)
*Effects*: If I models [forward_iterator](iterator.concept.forward#concept:forward_iterator "24.3.4.11Concept forward_­iterator[iterator.concept.forward]"), equivalent to:common_iterator tmp = *this;++*this;return tmp;
Otherwise, ifrequires(I& i) { { *i++ } -> [*can-reference*](iterator.synopsis#concept:can-reference "24.2Header <iterator>&nbsp;synopsis[iterator.synopsis]"); } is true or[indirectly_readable](iterator.concept.readable#concept:indirectly_readable "24.3.4.2Concept indirectly_­readable[iterator.concept.readable]")<I> && [constructible_from](concept.constructible#concept:constructible_from "18.4.11Concept constructible_­from[concept.constructible]")<iter_value_t<I>, iter_reference_t<I>> &&[move_constructible](concept.moveconstructible#concept:move_constructible "18.4.13Concept move_­constructible[concept.moveconstructible]")<iter_value_t<I>> is false,
equivalent to:return get<I>(v_)++;
Otherwise, equivalent to:*postfix-proxy* p(**this);++*this;return p; where *postfix-proxy* is the exposition-only class:class *postfix-proxy* { iter_value_t<I> keep_; constexpr *postfix-proxy*(iter_reference_t<I>&& x): keep_(std::forward<iter_reference_t<I>>(x)) {}public:constexpr const iter_value_t<I>& operator*() const noexcept {return keep_; }};
#### [24.5.5.6](#common.iter.cmp) Comparisons [[common.iter.cmp]](common.iter.cmp)
[🔗](#lib:operator==,common_iterator)
`template<class I2, [sentinel_for](iterator.concept.sentinel#concept:sentinel_for "24.3.4.7Concept sentinel_­for[iterator.concept.sentinel]")<I> S2>
requires [sentinel_for](iterator.concept.sentinel#concept:sentinel_for "24.3.4.7Concept sentinel_­for[iterator.concept.sentinel]")<S, I2>
friend constexpr bool operator==(
const common_iterator& x, const common_iterator<I2, S2>& y);
`
[1](#common.iter.cmp-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iterators.tex#L5767)
*Hardened preconditions*: x.v_.valueless_by_exception() and y.v_.valueless_by_exception() are each false[.](#common.iter.cmp-1.sentence-1)
[2](#common.iter.cmp-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iterators.tex#L5772)
*Returns*: true if i == j,
and otherwise get<i>(x.v_) == get<j>(y.v_),
where i is x.v_.index() and j is y.v_.index()[.](#common.iter.cmp-2.sentence-1)
[🔗](#lib:operator==,common_iterator_)
`template<class I2, [sentinel_for](iterator.concept.sentinel#concept:sentinel_for "24.3.4.7Concept sentinel_­for[iterator.concept.sentinel]")<I> S2>
requires [sentinel_for](iterator.concept.sentinel#concept:sentinel_for "24.3.4.7Concept sentinel_­for[iterator.concept.sentinel]")<S, I2> && [equality_comparable_with](concept.equalitycomparable#concept:equality_comparable_with "18.5.4Concept equality_­comparable[concept.equalitycomparable]")<I, I2>
friend constexpr bool operator==(
const common_iterator& x, const common_iterator<I2, S2>& y);
`
[3](#common.iter.cmp-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iterators.tex#L5788)
*Hardened preconditions*: x.v_.valueless_by_exception() and y.v_.valueless_by_exception() are each false[.](#common.iter.cmp-3.sentence-1)
[4](#common.iter.cmp-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iterators.tex#L5793)
*Returns*: true if i and j are each 1, and otherwiseget<i>(x.v_) == get<j>(y.v_), wherei is x.v_.index() and j is y.v_.index()[.](#common.iter.cmp-4.sentence-1)
[🔗](#lib:operator-,common_iterator)
`template<[sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8Concept sized_­sentinel_­for[iterator.concept.sizedsentinel]")<I> I2, [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8Concept sized_­sentinel_­for[iterator.concept.sizedsentinel]")<I> S2>
requires [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8Concept sized_­sentinel_­for[iterator.concept.sizedsentinel]")<S, I2>
friend constexpr iter_difference_t<I2> operator-(
const common_iterator& x, const common_iterator<I2, S2>& y);
`
[5](#common.iter.cmp-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iterators.tex#L5809)
*Hardened preconditions*: x.v_.valueless_by_exception() and y.v_.valueless_by_exception() are each false[.](#common.iter.cmp-5.sentence-1)
[6](#common.iter.cmp-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iterators.tex#L5814)
*Returns*: 0 if i and j are each 1, and otherwiseget<i>(x.v_) - get<j>(y.v_), wherei is x.v_.index() and j is y.v_.index()[.](#common.iter.cmp-6.sentence-1)
#### [24.5.5.7](#common.iter.cust) Customizations [[common.iter.cust]](common.iter.cust)
[🔗](#lib:iter_move,common_iterator)
`friend constexpr decltype(auto) iter_move(const common_iterator& i)
noexcept(noexcept(ranges::iter_move(declval<const I&>())))
requires [input_iterator](iterator.concept.input#concept:input_iterator "24.3.4.9Concept input_­iterator[iterator.concept.input]")<I>;
`
[1](#common.iter.cust-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iterators.tex#L5831)
*Hardened preconditions*: holds_alternative<I>(i.v_) is true[.](#common.iter.cust-1.sentence-1)
[2](#common.iter.cust-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iterators.tex#L5835)
*Effects*: Equivalent to: return ranges::iter_move(get<I>(i.v_));
[🔗](#lib:iter_swap,common_iterator)
`template<[indirectly_swappable](alg.req.ind.swap#concept:indirectly_swappable "24.3.7.4Concept indirectly_­swappable[alg.req.ind.swap]")<I> I2, class S2>
friend constexpr void iter_swap(const common_iterator& x, const common_iterator<I2, S2>& y)
noexcept(noexcept(ranges::iter_swap(declval<const I&>(), declval<const I2&>())));
`
[3](#common.iter.cust-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iterators.tex#L5848)
*Hardened preconditions*: holds_alternative<I>(x.v_) and holds_alternative<I2>(y.v_) are each true[.](#common.iter.cust-3.sentence-1)
[4](#common.iter.cust-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/iterators.tex#L5853)
*Effects*: Equivalent to ranges::iter_swap(get<I>(x.v_), get<I2>(y.v_))[.](#common.iter.cust-4.sentence-1)