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

533 lines
30 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.

[range.adjacent]
# 25 Ranges library [[ranges]](./#ranges)
## 25.7 Range adaptors [[range.adaptors]](range.adaptors#range.adjacent)
### 25.7.27 Adjacent view [range.adjacent]
#### [25.7.27.1](#overview) Overview [[range.adjacent.overview]](range.adjacent.overview)
[1](#overview-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L12539)
adjacent_view takes a view and
produces a view whose Mth element is
a tuple of references to
the Mth through (M+N−1)th elements of
the original view[.](#overview-1.sentence-1)
If the original view has fewer than N elements, the resulting view is empty[.](#overview-1.sentence-2)
[2](#overview-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L12547)
The name views::adjacent<N> denotes
a range adaptor object ([[range.adaptor.object]](range.adaptor.object "25.7.2Range adaptor objects"))[.](#overview-2.sentence-1)
Given a subexpression E and a constant expression N,
the expression views::adjacent<N>(E) is expression-equivalent to
- [(2.1)](#overview-2.1)
((void)E, auto(views::empty<tuple<>>)) if N is equal to 0 anddecltype((E)) models [forward_range](range.refinements#concept:forward_range "25.4.6Other range refinements[range.refinements]"),
- [(2.2)](#overview-2.2)
otherwise, adjacent_view<views::all_t<decltype((E))>, N>(E)[.](#overview-2.sentence-2)
[*Example [1](#overview-example-1)*: vector v = {1, 2, 3, 4};
for (auto i : v | views::adjacent<2>) { cout << "(" << std::get<0>(i) << ", " << std::get<1>(i) << ") "; // prints (1, 2) (2, 3) (3, 4)} — *end example*]
[3](#overview-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L12572)
Define *REPEAT*(T, N) as a pack of N types,
each of which denotes the same type as T[.](#overview-3.sentence-1)
#### [25.7.27.2](#view) Class template adjacent_view [[range.adjacent.view]](range.adjacent.view)
[🔗](#lib:adjacent_view)
namespace std::ranges {template<[forward_range](range.refinements#concept:forward_range "25.4.6Other range refinements[range.refinements]") V, size_t N>requires [view](range.view#concept:view "25.4.5Views[range.view]")<V> && (N > 0)class adjacent_view : public view_interface<adjacent_view<V, N>> { V *base_* = V(); // *exposition only*// [[range.adjacent.iterator]](#iterator "25.7.27.3Class template adjacent_­view::iterator"), class template adjacent_view::*iterator*template<bool> class *iterator*; // *exposition only*// [[range.adjacent.sentinel]](#sentinel "25.7.27.4Class template adjacent_­view::sentinel"), class template adjacent_view::*sentinel*template<bool> class *sentinel*; // *exposition only*struct *as-sentinel*{}; // *exposition only*public: adjacent_view() requires [default_initializable](concept.default.init#concept:default_initializable "18.4.12Concept default_­initializable[concept.default.init]")<V> = default; constexpr explicit adjacent_view(V base); constexpr V base() const & requires [copy_constructible](concept.copyconstructible#concept:copy_constructible "18.4.14Concept copy_­constructible[concept.copyconstructible]")<V> { return *base_*; }constexpr V base() && { return std::move(*base_*); }constexpr auto begin() requires (![*simple-view*](range.utility.helpers#concept:simple-view "25.5.2Helper concepts[range.utility.helpers]")<V>) {return *iterator*<false>(ranges::begin(*base_*), ranges::end(*base_*)); }constexpr auto begin() const requires [range](range.range#concept:range "25.4.2Ranges[range.range]")<const V> {return *iterator*<true>(ranges::begin(*base_*), ranges::end(*base_*)); }constexpr auto end() requires (![*simple-view*](range.utility.helpers#concept:simple-view "25.5.2Helper concepts[range.utility.helpers]")<V>) {if constexpr ([common_range](range.refinements#concept:common_range "25.4.6Other range refinements[range.refinements]")<V>) {return *iterator*<false>(*as-sentinel*{}, ranges::begin(*base_*), ranges::end(*base_*)); } else {return *sentinel*<false>(ranges::end(*base_*)); }}constexpr auto end() const requires [range](range.range#concept:range "25.4.2Ranges[range.range]")<const V> {if constexpr ([common_range](range.refinements#concept:common_range "25.4.6Other range refinements[range.refinements]")<const V>) {return *iterator*<true>(*as-sentinel*{}, ranges::begin(*base_*), ranges::end(*base_*)); } else {return *sentinel*<true>(ranges::end(*base_*)); }}constexpr auto size() requires [sized_range](range.sized#concept:sized_range "25.4.4Sized ranges[range.sized]")<V>; constexpr auto size() const requires [sized_range](range.sized#concept:sized_range "25.4.4Sized ranges[range.sized]")<const V>; constexpr auto reserve_hint() requires [approximately_sized_range](range.approximately.sized#concept:approximately_sized_range "25.4.3Approximately sized ranges[range.approximately.sized]")<V>; constexpr auto reserve_hint() const requires [approximately_sized_range](range.approximately.sized#concept:approximately_sized_range "25.4.3Approximately sized ranges[range.approximately.sized]")<const V>; };}
[🔗](#lib:adjacent_view,constructor)
`constexpr explicit adjacent_view(V base);
`
[1](#view-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L12642)
*Effects*: Initializes *base_* with std::move(base)[.](#view-1.sentence-1)
[🔗](#lib:size,adjacent_view)
`constexpr auto size() requires [sized_range](range.sized#concept:sized_range "25.4.4Sized ranges[range.sized]")<V>;
constexpr auto size() const requires [sized_range](range.sized#concept:sized_range "25.4.4Sized ranges[range.sized]")<const V>;
`
[2](#view-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L12654)
*Effects*: Equivalent to:using ST = decltype(ranges::size(*base_*));using CT = common_type_t<ST, size_t>;auto sz = static_cast<CT>(ranges::size(*base_*));
sz -= std::min<CT>(sz, N - 1);return static_cast<ST>(sz);
[🔗](#lib:reserve_hint,adjacent_view)
`constexpr auto reserve_hint() requires [approximately_sized_range](range.approximately.sized#concept:approximately_sized_range "25.4.3Approximately sized ranges[range.approximately.sized]")<V>;
constexpr auto reserve_hint() const requires [approximately_sized_range](range.approximately.sized#concept:approximately_sized_range "25.4.3Approximately sized ranges[range.approximately.sized]")<const V>;
`
[3](#view-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L12673)
*Effects*: Equivalent to:using DT = range_difference_t<decltype((*base_*))>;using CT = common_type_t<DT, size_t>;auto sz = static_cast<CT>(ranges::reserve_hint(*base_*));
sz -= std::min<CT>(sz, N - 1);return *to-unsigned-like*(sz);
#### [25.7.27.3](#iterator) Class template adjacent_view::*iterator* [[range.adjacent.iterator]](range.adjacent.iterator)
[🔗](#lib:adjacent_view::iterator)
namespace std::ranges {template<[forward_range](range.refinements#concept:forward_range "25.4.6Other range refinements[range.refinements]") V, size_t N>requires [view](range.view#concept:view "25.4.5Views[range.view]")<V> && (N > 0)template<bool Const>class adjacent_view<V, N>::*iterator* {using *Base* = *maybe-const*<Const, V>; // *exposition only* array<iterator_t<*Base*>, N> *current_* = array<iterator_t<*Base*>, N>(); // *exposition only*constexpr *iterator*(iterator_t<*Base*> first, sentinel_t<*Base*> last); // *exposition only*constexpr *iterator*(*as-sentinel*, iterator_t<*Base*> first, iterator_t<*Base*> last); // *exposition only*public:using iterator_category = input_iterator_tag; using iterator_concept = *see below*; using value_type = tuple<*REPEAT*(range_value_t<*Base*>, N)...>; using difference_type = range_difference_t<*Base*>; *iterator*() = default; constexpr *iterator*(*iterator*<!Const> i)requires Const && [convertible_to](concept.convertible#concept:convertible_to "18.4.4Concept convertible_­to[concept.convertible]")<iterator_t<V>, iterator_t<*Base*>>; constexpr auto operator*() const; constexpr *iterator*& operator++(); constexpr *iterator* operator++(int); constexpr *iterator*& operator--() requires [bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6Other range refinements[range.refinements]")<*Base*>; constexpr *iterator* operator--(int) requires [bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6Other range refinements[range.refinements]")<*Base*>; constexpr *iterator*& operator+=(difference_type x)requires [random_access_range](range.refinements#concept:random_access_range "25.4.6Other range refinements[range.refinements]")<*Base*>; constexpr *iterator*& operator-=(difference_type x)requires [random_access_range](range.refinements#concept:random_access_range "25.4.6Other range refinements[range.refinements]")<*Base*>; constexpr auto operator[](difference_type n) constrequires [random_access_range](range.refinements#concept:random_access_range "25.4.6Other range refinements[range.refinements]")<*Base*>; friend constexpr bool operator==(const *iterator*& x, const *iterator*& y); friend constexpr bool operator<(const *iterator*& x, const *iterator*& y)requires [random_access_range](range.refinements#concept:random_access_range "25.4.6Other range refinements[range.refinements]")<*Base*>; friend constexpr bool operator>(const *iterator*& x, const *iterator*& y)requires [random_access_range](range.refinements#concept:random_access_range "25.4.6Other range refinements[range.refinements]")<*Base*>; friend constexpr bool operator<=(const *iterator*& x, const *iterator*& y)requires [random_access_range](range.refinements#concept:random_access_range "25.4.6Other range refinements[range.refinements]")<*Base*>; friend constexpr bool operator>=(const *iterator*& x, const *iterator*& y)requires [random_access_range](range.refinements#concept:random_access_range "25.4.6Other range refinements[range.refinements]")<*Base*>; friend constexpr auto operator<=>(const *iterator*& x, const *iterator*& y)requires [random_access_range](range.refinements#concept:random_access_range "25.4.6Other range refinements[range.refinements]")<*Base*> &&[three_way_comparable](cmp.concept#concept:three_way_comparable "17.12.4Concept three_­way_­comparable[cmp.concept]")<iterator_t<*Base*>>; friend constexpr *iterator* operator+(const *iterator*& i, difference_type n)requires [random_access_range](range.refinements#concept:random_access_range "25.4.6Other range refinements[range.refinements]")<*Base*>; friend constexpr *iterator* operator+(difference_type n, const *iterator*& i)requires [random_access_range](range.refinements#concept:random_access_range "25.4.6Other range refinements[range.refinements]")<*Base*>; friend constexpr *iterator* operator-(const *iterator*& i, difference_type n)requires [random_access_range](range.refinements#concept:random_access_range "25.4.6Other range refinements[range.refinements]")<*Base*>; friend constexpr difference_type operator-(const *iterator*& x, const *iterator*& y)requires [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8Concept sized_­sentinel_­for[iterator.concept.sizedsentinel]")<iterator_t<*Base*>, iterator_t<*Base*>>; 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](alg.req.ind.swap#concept:indirectly_swappable "24.3.7.4Concept indirectly_­swappable[alg.req.ind.swap]")<iterator_t<*Base*>>; };}
[1](#iterator-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L12753)
*iterator*::iterator_concept is defined as follows:
- [(1.1)](#iterator-1.1)
If *Base* models [random_access_range](range.refinements#concept:random_access_range "25.4.6Other range refinements[range.refinements]"),
then iterator_concept denotes random_access_iterator_tag[.](#iterator-1.1.sentence-1)
- [(1.2)](#iterator-1.2)
Otherwise, if *Base* models [bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6Other range refinements[range.refinements]"),
then iterator_concept denotes bidirectional_iterator_tag[.](#iterator-1.2.sentence-1)
- [(1.3)](#iterator-1.3)
Otherwise, iterator_concept denotes forward_iterator_tag[.](#iterator-1.3.sentence-1)
[2](#iterator-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L12766)
If the invocation of any non-const member function of *iterator* exits via an exception, the *iterator* acquires a singular value[.](#iterator-2.sentence-1)
[🔗](#lib:adjacent_view::iterator,constructor)
`constexpr iterator(iterator_t<Base> first, sentinel_t<Base> last);
`
[3](#iterator-3)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L12776)
*Postconditions*: *current_*[0] == first is true, and
for every integer 1≤i<N,*current_*[i] == ranges::next(*current_*[i-1], 1, last) is true[.](#iterator-3.sentence-1)
[🔗](#lib:adjacent_view::iterator,constructor_)
`constexpr iterator(as-sentinel, iterator_t<Base> first, iterator_t<Base> last);
`
[4](#iterator-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L12790)
*Postconditions*: If *Base* does not model [bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6Other range refinements[range.refinements]"),
each element of *current_* is equal to *last*[.](#iterator-4.sentence-1)
Otherwise, *current_*[N-1] == last is true, and
for every integer ‰¤i<(ˆ’1),*current_*[i] == ranges::prev(*current_*[i+1], 1, first) is true[.](#iterator-4.sentence-2)
[🔗](#lib:adjacent_view::iterator,constructor__)
`constexpr iterator(iterator<!Const> i)
requires Const && [convertible_to](concept.convertible#concept:convertible_to "18.4.4Concept convertible_­to[concept.convertible]")<iterator_t<V>, iterator_t<Base>>;
`
[5](#iterator-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L12807)
*Effects*: Initializes each element of *current_* with the corresponding element of i.*current_* as an xvalue[.](#iterator-5.sentence-1)
[🔗](#lib:operator*,adjacent_view::iterator)
`constexpr auto operator*() const;
`
[6](#iterator-6)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L12819)
*Effects*: Equivalent to:return *tuple-transform*([](auto& i) -> decltype(auto) { return *i; }, *current_*);
[🔗](#lib:operator++,adjacent_view::iterator)
`constexpr iterator& operator++();
`
[7](#iterator-7)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L12833)
*Preconditions*: *current_*.back() is incrementable[.](#iterator-7.sentence-1)
[8](#iterator-8)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L12837)
*Postconditions*: Each element of *current_* is equal to ranges::next(i),
where i is the value of that element before the call[.](#iterator-8.sentence-1)
[9](#iterator-9)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L12842)
*Returns*: *this[.](#iterator-9.sentence-1)
[🔗](#lib:operator++,adjacent_view::iterator_)
`constexpr iterator operator++(int);
`
[10](#iterator-10)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L12853)
*Effects*: Equivalent to:auto tmp = *this;++*this;return tmp;
[🔗](#lib:operator--,adjacent_view::iterator)
`constexpr iterator& operator--() requires [bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6Other range refinements[range.refinements]")<Base>;
`
[11](#iterator-11)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L12869)
*Preconditions*: *current_*.front() is decrementable[.](#iterator-11.sentence-1)
[12](#iterator-12)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L12873)
*Postconditions*: Each element of *current_* is equal to ranges::prev(i),
where i is the value of that element before the call[.](#iterator-12.sentence-1)
[13](#iterator-13)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L12878)
*Returns*: *this[.](#iterator-13.sentence-1)
[🔗](#lib:operator--,adjacent_view::iterator_)
`constexpr iterator operator--(int) requires [bidirectional_range](range.refinements#concept:bidirectional_range "25.4.6Other range refinements[range.refinements]")<Base>;
`
[14](#iterator-14)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L12889)
*Effects*: Equivalent to:auto tmp = *this;--*this;return tmp;
[🔗](#lib:operator+=,adjacent_view::iterator)
`constexpr iterator& operator+=(difference_type x)
requires [random_access_range](range.refinements#concept:random_access_range "25.4.6Other range refinements[range.refinements]")<Base>;
`
[15](#iterator-15)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L12906)
*Preconditions*: *current_*.back() + x has well-defined behavior[.](#iterator-15.sentence-1)
[16](#iterator-16)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L12910)
*Postconditions*: Each element of *current_* is equal to i + x,
where i is the value of that element before the call[.](#iterator-16.sentence-1)
[17](#iterator-17)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L12915)
*Returns*: *this[.](#iterator-17.sentence-1)
[🔗](#lib:operator-=,adjacent_view::iterator)
`constexpr iterator& operator-=(difference_type x)
requires [random_access_range](range.refinements#concept:random_access_range "25.4.6Other range refinements[range.refinements]")<Base>;
`
[18](#iterator-18)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L12927)
*Preconditions*: *current_*.front() - x has well-defined behavior[.](#iterator-18.sentence-1)
[19](#iterator-19)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L12931)
*Postconditions*: Each element of *current_* is equal to i - x,
where i is the value of that element before the call[.](#iterator-19.sentence-1)
[20](#iterator-20)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L12936)
*Returns*: *this[.](#iterator-20.sentence-1)
[🔗](#lib:operator%5b%5d,adjacent_view::iterator)
`constexpr auto operator[](difference_type n) const
requires [random_access_range](range.refinements#concept:random_access_range "25.4.6Other range refinements[range.refinements]")<Base>;
`
[21](#iterator-21)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L12948)
*Effects*: Equivalent to:return *tuple-transform*([&](auto& i) -> decltype(auto) { return i[n]; }, *current_*);
[🔗](#lib:operator==,adjacent_view::iterator)
`friend constexpr bool operator==(const iterator& x, const iterator& y);
`
[22](#iterator-22)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L12962)
*Returns*: x.*current_*.back() == y.*current_*.back()[.](#iterator-22.sentence-1)
[🔗](#lib:operator%3c,adjacent_view::iterator)
`friend constexpr bool operator<(const iterator& x, const iterator& y)
requires [random_access_range](range.refinements#concept:random_access_range "25.4.6Other range refinements[range.refinements]")<Base>;
`
[23](#iterator-23)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L12974)
*Returns*: x.*current_*.back() < y.*current_*.back()[.](#iterator-23.sentence-1)
[🔗](#lib:operator%3e,adjacent_view::iterator)
`friend constexpr bool operator>(const iterator& x, const iterator& y)
requires [random_access_range](range.refinements#concept:random_access_range "25.4.6Other range refinements[range.refinements]")<Base>;
`
[24](#iterator-24)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L12986)
*Effects*: Equivalent to: return y < x;
[🔗](#lib:operator%3c=,adjacent_view::iterator)
`friend constexpr bool operator<=(const iterator& x, const iterator& y)
requires [random_access_range](range.refinements#concept:random_access_range "25.4.6Other range refinements[range.refinements]")<Base>;
`
[25](#iterator-25)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L12998)
*Effects*: Equivalent to: return !(y < x);
[🔗](#lib:operator%3e=,adjacent_view::iterator)
`friend constexpr bool operator>=(const iterator& x, const iterator& y)
requires [random_access_range](range.refinements#concept:random_access_range "25.4.6Other range refinements[range.refinements]")<Base>;
`
[26](#iterator-26)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L13010)
*Effects*: Equivalent to: return !(x < y);
[🔗](#lib:operator%3c=%3e,adjacent_view::iterator)
`friend constexpr auto operator<=>(const iterator& x, const iterator& y)
requires [random_access_range](range.refinements#concept:random_access_range "25.4.6Other range refinements[range.refinements]")<Base> &&
[three_way_comparable](cmp.concept#concept:three_way_comparable "17.12.4Concept three_­way_­comparable[cmp.concept]")<iterator_t<Base>>;
`
[27](#iterator-27)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L13023)
*Returns*: x.*current_*.back() <=> y.*current_*.back()[.](#iterator-27.sentence-1)
[🔗](#lib:operator+,adjacent_view::iterator)
`friend constexpr iterator operator+(const iterator& i, difference_type n)
requires [random_access_range](range.refinements#concept:random_access_range "25.4.6Other range refinements[range.refinements]")<Base>;
friend constexpr iterator operator+(difference_type n, const iterator& i)
requires [random_access_range](range.refinements#concept:random_access_range "25.4.6Other range refinements[range.refinements]")<Base>;
`
[28](#iterator-28)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L13037)
*Effects*: Equivalent to:auto r = i;
r += n;return r;
[🔗](#lib:operator-,adjacent_view::iterator)
`friend constexpr iterator operator-(const iterator& i, difference_type n)
requires [random_access_range](range.refinements#concept:random_access_range "25.4.6Other range refinements[range.refinements]")<Base>;
`
[29](#iterator-29)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L13054)
*Effects*: Equivalent to:auto r = i;
r -= n;return r;
[🔗](#lib:operator-,adjacent_view::iterator_)
`friend constexpr difference_type operator-(const iterator& x, const iterator& y)
requires [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8Concept sized_­sentinel_­for[iterator.concept.sizedsentinel]")<iterator_t<Base>, iterator_t<Base>>;
`
[30](#iterator-30)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L13071)
*Effects*: Equivalent to:return x.*current_*.back() - y.*current_*.back();
[🔗](#lib:iter_move,adjacent_view::iterator)
`friend constexpr auto iter_move(const iterator& i) noexcept(see below);
`
[31](#iterator-31)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L13083)
*Effects*: Equivalent to:return *tuple-transform*(ranges::iter_move, i.*current_*);
[32](#iterator-32)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L13088)
*Remarks*: The exception specification is equivalent to:noexcept(ranges::iter_move(declval<const iterator_t<*Base*>&>())) && is_nothrow_move_constructible_v<range_rvalue_reference_t<*Base*>>
[🔗](#lib:iter_swap,adjacent_view::iterator)
`friend constexpr void iter_swap(const iterator& l, const iterator& r) noexcept(see below)
requires [indirectly_swappable](alg.req.ind.swap#concept:indirectly_swappable "24.3.7.4Concept indirectly_­swappable[alg.req.ind.swap]")<iterator_t<Base>>;
`
[33](#iterator-33)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L13104)
*Preconditions*: None of the iterators in l.*current_* is equal to
an iterator in r.*current_*[.](#iterator-33.sentence-1)
[34](#iterator-34)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L13109)
*Effects*: For every integer 0≤i<N,
performsranges::iter_swap(l.*current_*[i], r.*current_*[i])[.](#iterator-34.sentence-1)
[35](#iterator-35)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L13115)
*Remarks*: The exception specification is equivalent to:noexcept(ranges::iter_swap(declval<iterator_t<*Base*>>(), declval<iterator_t<*Base*>>()))
#### [25.7.27.4](#sentinel) Class template adjacent_view::*sentinel* [[range.adjacent.sentinel]](range.adjacent.sentinel)
[🔗](#lib:adjacent_view::sentinel)
namespace std::ranges {template<[forward_range](range.refinements#concept:forward_range "25.4.6Other range refinements[range.refinements]") V, size_t N>requires [view](range.view#concept:view "25.4.5Views[range.view]")<V> && (N > 0)template<bool Const>class adjacent_view<V, N>::*sentinel* {using *Base* = *maybe-const*<Const, V>; // *exposition only* sentinel_t<*Base*> *end_* = sentinel_t<*Base*>(); // *exposition only*constexpr explicit *sentinel*(sentinel_t<*Base*> end); // *exposition only*public:*sentinel*() = default; constexpr *sentinel*(*sentinel*<!Const> i)requires Const && [convertible_to](concept.convertible#concept:convertible_to "18.4.4Concept 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.7Concept 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); template<bool OtherConst>requires [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8Concept sized_­sentinel_­for[iterator.concept.sizedsentinel]")<sentinel_t<*Base*>, iterator_t<*maybe-const*<OtherConst, V>>>friend constexpr range_difference_t<*maybe-const*<OtherConst, V>>operator-(const *iterator*<OtherConst>& x, const *sentinel*& y); template<bool OtherConst>requires [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8Concept sized_­sentinel_­for[iterator.concept.sizedsentinel]")<sentinel_t<*Base*>, iterator_t<*maybe-const*<OtherConst, V>>>friend constexpr range_difference_t<*maybe-const*<OtherConst, V>>operator-(const *sentinel*& y, const *iterator*<OtherConst>& x); };}
[🔗](#lib:adjacent_view::sentinel,constructor)
`constexpr explicit sentinel(sentinel_t<Base> end);
`
[1](#sentinel-1)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L13164)
*Effects*: Initializes *end_* with end[.](#sentinel-1.sentence-1)
[🔗](#lib:adjacent_view::sentinel,constructor_)
`constexpr sentinel(sentinel<!Const> i)
requires Const && [convertible_to](concept.convertible#concept:convertible_to "18.4.4Concept convertible_­to[concept.convertible]")<sentinel_t<V>, sentinel_t<Base>>;
`
[2](#sentinel-2)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L13176)
*Effects*: Initializes *end_* with std::move(i.*end_*)[.](#sentinel-2.sentence-1)
[🔗](#lib:operator==,adjacent_view::sentinel)
`template<bool OtherConst>
requires [sentinel_for](iterator.concept.sentinel#concept:sentinel_for "24.3.4.7Concept 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#L13189)
*Effects*: Equivalent to: return x.*current_*.back() == y.*end_*;
[🔗](#lib:operator-,adjacent_view::sentinel)
`template<bool OtherConst>
requires [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8Concept sized_­sentinel_­for[iterator.concept.sizedsentinel]")<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
friend constexpr range_difference_t<maybe-const<OtherConst, V>>
operator-(const iterator<OtherConst>& x, const sentinel& y);
`
[4](#sentinel-4)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L13203)
*Effects*: Equivalent to: return x.*current_*.back() - y.*end_*;
[🔗](#lib:operator-,adjacent_view::sentinel_)
`template<bool OtherConst>
requires [sized_sentinel_for](iterator.concept.sizedsentinel#concept:sized_sentinel_for "24.3.4.8Concept sized_­sentinel_­for[iterator.concept.sizedsentinel]")<sentinel_t<Base>, iterator_t<maybe-const<OtherConst, V>>>
friend constexpr range_difference_t<maybe-const<OtherConst, V>>
operator-(const sentinel& y, const iterator<OtherConst>& x);
`
[5](#sentinel-5)
[#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/ranges.tex#L13217)
*Effects*: Equivalent to: return y.*end_* - x.*current_*.back();