diff --git a/source/containers.tex b/source/containers.tex index e7ce7aaebc..7a97772ec7 100644 --- a/source/containers.tex +++ b/source/containers.tex @@ -6296,6 +6296,7 @@ constexpr operator bool() const noexcept; constexpr reference& operator=(bool x) noexcept; constexpr reference& operator=(const reference& x) noexcept; + constexpr const reference& operator=(bool x) const noexcept; constexpr void flip() noexcept; // flips the bit }; diff --git a/source/iterators.tex b/source/iterators.tex index 8b3bc34ee2..e29204ebd7 100644 --- a/source/iterators.tex +++ b/source/iterators.tex @@ -1381,10 +1381,11 @@ \pnum Expressions of integer-class type are -explicitly convertible to any integral type. +explicitly convertible to any integral type as well as any integer-class type. Expressions of integral type are both implicitly and explicitly convertible to any integer-class type. -Conversions between integral and integer-class types +Conversions between integral and integer-class types and +between two integer-class types do not exit via an exception. \pnum @@ -1434,6 +1435,14 @@ if it models \tcode{\libconcept{unsigned_integral}} or if it is an unsigned-integer-class type. +\pnum +For any two integer-like types \tcode{I1} and \tcode{I2}, +at least one of which is an integer-class type, +\tcode{common_type_t} denotes an integer-like type +whose width is not less than that of \tcode{I1} or \tcode{I2}. +If both \tcode{I1} and \tcode{I2} are signed-integer-like types, +then \tcode{common_type_t} is also a signed-integer-like type. + \pnum \tcode{\exposid{is-integer-like}} is \tcode{true} if and only if \tcode{I} is an integer-like type. diff --git a/source/ranges.tex b/source/ranges.tex index d01c9de8e2..8b9853c5fe 100644 --- a/source/ranges.tex +++ b/source/ranges.tex @@ -329,6 +329,52 @@ inline constexpr auto @\libmember{keys}{views}@ = elements<0>; inline constexpr auto @\libmember{values}{views}@ = elements<1>; } + + // \ref{range.zip}, zip view + template<@\libconcept{input_range}@... Views> + requires (@\libconcept{view}@ && ...) && (sizeof...(Views) > 0) + class zip_view; + + template + inline constexpr bool enable_borrowed_range> = + (enable_borrowed_range && ...); + + namespace views { inline constexpr @\unspec@ zip = @\unspec@; } + + // \ref{range.zip.transform}, zip transform view + template<@\libconcept{copy_constructible}@ F, @\libconcept{input_range}@... Views> + requires (@\libconcept{view}@ && ...) && (sizeof...(Views) > 0) && is_object_v && + @\libconcept{regular_invocable}@...> && + @\exposconcept{can-reference}@...>> + class zip_transform_view; + + namespace views { inline constexpr @\unspec@ zip_transform = @\unspec@; } + + // \ref{range.adjacent}, adjacent view + template<@\libconcept{forward_range}@ V, size_t N> + requires @\libconcept{view}@ && (N > 0) + class adjacent_view; + + template + inline constexpr bool enable_borrowed_range> = + enable_borrowed_range; + + namespace views { + template + inline constexpr @\unspec@ adjacent = @\unspec@ ; + inline constexpr auto @\libmember{pairwise}{views}@ = adjacent<2>; + } + + // \ref{range.adjacent.transform}, adjacent transform view + template<@\libconcept{forward_range}@ V, @\libconcept{copy_constructible}@ F, size_t N> + requires @\seebelow@ + class adjacent_transform_view; + + namespace views { + template + inline constexpr @\unspec@ adjacent_transform = @\unspec@; + inline constexpr auto @\libmember{pairwise_transform}{views}@ = adjacent_transform<2>; + } } namespace std { @@ -7574,3 +7620,2414 @@ \effects Equivalent to: \tcode{return x.\exposid{end_} - y.\exposid{current_};} \end{itemdescr} + +\rSec2[range.zip]{Zip view} + +\rSec3[range.zip.overview]{Overview} + +\pnum +\indexlibraryglobal{zip_view}% +\tcode{zip_view} takes any number of \libconcept{view}s and +produces a \libconcept{view} of tuples of references +to the corresponding elements of the constituent views. + +\pnum +\indexlibrarymember{zip}{views}% +The name \tcode{views::zip} denotes +a customization point object\iref{customization.point.object}. +Given a pack of subexpressions \tcode{Es...}, +the expression \tcode{views::zip(Es...)} is expression-equivalent to +\begin{itemize} +\item +\tcode{auto(views::empty>)} +if \tcode{Es} is an empty pack, +\item +otherwise, \tcode{zip_view...>(Es...)}. +\end{itemize} + +\begin{example} +\begin{codeblock} +vector v = {1, 2}; +list l = {'a', 'b', 'c'}; + +auto z = views::zip(v, l); +range_reference_t f = z.front(); // \tcode{f} is a \tcode{pair} + // that refers to the first element of \tcode{v} and \tcode{l} + +for (auto&& [x, y] : z) { + cout << '(' << x << ", " << y << ") "; // prints: (1, a) (2, b) +} +\end{codeblock} +\end{example} + +\rSec3[range.zip.view]{Class template \tcode{zip_view}} + +\indexlibrarymember{begin}{zip_view}% +\indexlibrarymember{end}{zip_view}% +\indexlibrarymember{size}{zip_view}% +\begin{codeblock} +namespace std::ranges { + template + concept @\defexposconcept{zip-is-common}@ = // \expos + (sizeof...(Rs) == 1 && (@\libconcept{common_range}@ && ...)) || + (!(@\libconcept{bidirectional_range}@ && ...) && (@\libconcept{common_range}@ && ...)) || + ((@\libconcept{random_access_range}@ && ...) && (@\libconcept{sized_range}@ && ...)); + + template + using @\exposid{tuple-or-pair}@ = @\seebelow@; // \expos + + template + constexpr auto @\exposid{tuple-transform}@(F&& f, Tuple&& tuple) { // \expos + return apply([&](Ts&&... elements) { + return @\exposid{tuple-or-pair}@...>( + invoke(f, std::forward(elements))... + ); + }, std::forward(tuple)); + } + + template + constexpr void @\exposid{tuple-for-each}@(F&& f, Tuple&& tuple) { // \expos + apply([&](Ts&&... elements) { + (invoke(f, std::forward(elements)), ...); + }, std::forward(tuple)); + } + + template<@\libconcept{input_range}@... Views> + requires (@\libconcept{view}@ && ...) && (sizeof...(Views) > 0) + class zip_view : public view_interface> { + tuple @\exposid{views_}@; // \expos + + // \ref{range.zip.iterator}, class template \tcode{zip_view::\exposid{iterator}} + template class @\exposid{iterator}@; // \expos + // \ref{range.zip.sentinel}, class template \tcode{zip_view::\exposid{sentinel}} + template class @\exposid{sentinel}@; // \expos + + public: + zip_view() = default; + constexpr explicit zip_view(Views... views); + + constexpr auto begin() requires (!(@\exposconcept{simple-view}@ && ...)) { + return @\exposid{iterator}@(@\exposid{tuple-transform}@(ranges::begin, @\exposid{views_}@)); + } + constexpr auto begin() const requires (@\libconcept{range}@ && ...) { + return @\exposid{iterator}@(@\exposid{tuple-transform}@(ranges::begin, @\exposid{views_}@)); + } + + constexpr auto end() requires (!(@\exposconcept{simple-view}@ && ...)) { + if constexpr (!@\exposconcept{zip-is-common}@) { + return @\exposid{sentinel}@(@\exposid{tuple-transform}@(ranges::end, @\exposid{views_}@)); + } else if constexpr ((@\libconcept{random_access_range}@ && ...)) { + return begin() + iter_difference_t<@\exposid{iterator}@>(size()); + } else { + return @\exposid{iterator}@(@\exposid{tuple-transform}@(ranges::end, @\exposid{views_}@)); + } + } + + constexpr auto end() const requires (@\libconcept{range}@ && ...) { + if constexpr (!@\exposconcept{zip-is-common}@) { + return @\exposid{sentinel}@(@\exposid{tuple-transform}@(ranges::end, @\exposid{views_}@)); + } else if constexpr ((@\libconcept{random_access_range}@ && ...)) { + return begin() + iter_difference_t<@\exposid{iterator}@>(size()); + } else { + return @\exposid{iterator}@(@\exposid{tuple-transform}@(ranges::end, @\exposid{views_}@)); + } + } + + constexpr auto size() requires (@\libconcept{sized_range}@ && ...); + constexpr auto size() const requires (@\libconcept{sized_range}@ && ...); + }; + + template + zip_view(Rs&&...) -> zip_view...>; +} +\end{codeblock} + +\pnum +Given some pack of types \tcode{Ts}, +the alias template \exposid{tuple-or-pair} is defined as follows: +\begin{itemize} +\item +If \tcode{sizeof...(Ts)} is 2, +\tcode{\exposid{tuple-or-pair}} denotes \tcode{pair}. +\item +Otherwise, \tcode{\exposid{tuple-or-pair}} denotes \tcode{tuple}. +\end{itemize} + +\pnum +Two \tcode{zip_view} objects have the same underlying sequence if and only if +the corresponding elements of \exposid{views_} are equal\iref{concepts.equality} +and have the same underlying sequence. +\begin{note} +In particular, comparison of iterators obtained from \tcode{zip_view} objects +that do not have the same underlying sequence +is not required to produce meaningful results\iref{iterator.concept.forward}. +\end{note} + +\begin{itemdecl} +constexpr explicit zip_view(Views... views); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \exposid{views_} with \tcode{std::move(views)...}. +\end{itemdescr} + +\begin{itemdecl} +constexpr auto size() requires (@\libconcept{sized_range}@ && ...); +constexpr auto size() const requires (@\libconcept{sized_range}@ && ...); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +return apply([](auto... sizes) { + using CT = @\exposid{make-unsigned-like-t}@>; + return ranges::min({CT(sizes)...}); +}, @\exposid{tuple-transform}@(ranges::size, @\exposid{views_}@)); +\end{codeblock} +\end{itemdescr} + +\rSec3[range.zip.iterator]{Class template \tcode{zip_view::\exposid{iterator}}} + +\indexlibraryglobal{zip_view::iterator}% +\begin{codeblock} +namespace std::ranges { + template + concept @\defexposconcept{all-random-access}@ = // \expos + (@\libconcept{random_access_range}@<@\exposid{maybe-const}@> && ...); + template + concept @\defexposconcept{all-bidirectional}@ = // \expos + (@\libconcept{bidirectional_range}@<@\exposid{maybe-const}@> && ...); + template + concept @\defexposconcept{all-forward}@ = // \expos + (@\libconcept{forward_range}@<@\exposid{maybe-const}@> && ...); + + template<@\libconcept{input_range}@... Views> + requires (@\libconcept{view}@ && ...) && (sizeof...(Views) > 0) + template + class zip_view::@\exposid{iterator}@ { + @\exposid{tuple-or-pair}@>...> @\exposid{current_}@; // \expos + constexpr explicit @\exposid{iterator}@(@\exposid{tuple-or-pair}@>...>); + // \expos + public: + using iterator_category = input_iterator_tag; // not always present + using iterator_concept = @\seebelow@; + using value_type = @\exposid{tuple-or-pair}@>...>; + using difference_type = common_type_t>...>; + + @\exposid{iterator}@() = default; + constexpr @\exposid{iterator}@(@\exposid{iterator}@ i) + requires Const && (@\libconcept{convertible_to}@, + iterator_t<@\exposid{maybe-const}@>> && ...); + + constexpr auto operator*() const; + constexpr @\exposid{iterator}@& operator++(); + constexpr void operator++(int); + constexpr @\exposid{iterator}@ operator++(int) requires @\exposconcept{all-forward}@; + + constexpr @\exposid{iterator}@& operator--() requires @\exposconcept{all-bidirectional}@; + constexpr @\exposid{iterator}@ operator--(int) requires @\exposconcept{all-bidirectional}@; + + constexpr @\exposid{iterator}@& operator+=(difference_type x) + requires @\exposconcept{all-random-access}@; + constexpr @\exposid{iterator}@& operator-=(difference_type x) + requires @\exposconcept{all-random-access}@; + + constexpr auto operator[](difference_type n) const + requires @\exposconcept{all-random-access}@; + + friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires (@\libconcept{equality_comparable}@>> && ...); + + friend constexpr bool operator<(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\exposconcept{all-random-access}@; + friend constexpr bool operator>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\exposconcept{all-random-access}@; + friend constexpr bool operator<=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\exposconcept{all-random-access}@; + friend constexpr bool operator>=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\exposconcept{all-random-access}@; + friend constexpr auto operator<=>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\exposconcept{all-random-access}@ && + (@\libconcept{three_way_comparable}@>> && ...); + + friend constexpr @\exposid{iterator}@ operator+(const @\exposid{iterator}@& i, difference_type n) + requires @\exposconcept{all-random-access}@; + friend constexpr @\exposid{iterator}@ operator+(difference_type n, const @\exposid{iterator}@& i) + requires @\exposconcept{all-random-access}@; + friend constexpr @\exposid{iterator}@ operator-(const @\exposid{iterator}@& i, difference_type n) + requires @\exposconcept{all-random-access}@; + friend constexpr difference_type operator-(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires (@\libconcept{sized_sentinel_for}@>, + iterator_t<@\exposid{maybe-const}@>> && ...); + + friend constexpr auto iter_move(const @\exposid{iterator}@& i) noexcept(@\seebelow@); + + friend constexpr void iter_swap(const @\exposid{iterator}@& l, const @\exposid{iterator}@& r) noexcept(@\seebelow@) + requires (@\libconcept{indirectly_swappable}@>> && ...); + }; +} +\end{codeblock} + +\pnum +\tcode{\exposid{iterator}::iterator_concept} is defined as follows: +\begin{itemize} +\item +If \tcode{\exposconcept{all-random-access}} is modeled, +then \tcode{iterator_concept} denotes \tcode{random_access_iterator_tag}. +\item +Otherwise, +if \tcode{\exposconcept{all-bidirectional}} is modeled, +then \tcode{iterator_concept} denotes \tcode{bidirectional_iterator_tag}. +\item +Otherwise, +if \tcode{\exposconcept{all-forward}} is modeled, +then \tcode{iterator_concept} denotes \tcode{for\-ward_iterator_tag}. +\item +Otherwise, \tcode{iterator_concept} denotes \tcode{input_iterator_tag}. +\end{itemize} + +\pnum +\tcode{\exposid{iterator}::iterator_category} is present +if and only if \tcode{\exposconcept{all-forward}} is modeled. + +\pnum +If the invocation of any non-const member function of \exposid{iterator} +exits via an exception, +the iterator acquires a singular value. + +\begin{itemdecl} +constexpr explicit @\exposid{iterator}@(@\exposid{tuple-or-pair}@>...> current); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \exposid{current_} with \tcode{std::move(current)}. +\end{itemdescr} + +\begin{itemdecl} +constexpr @\exposid{iterator}@(@\exposid{iterator}@ i) + requires Const && + (@\libconcept{convertible_to}@, iterator_t<@\exposid{maybe-const}@>> && ...); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \exposid{current_} with \tcode{std::move(i.\exposid{current_})}. +\end{itemdescr} + +\begin{itemdecl} +constexpr auto operator*() const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +return @\exposid{tuple-transform}@([](auto& i) -> decltype(auto) { return *i; }, @\exposid{current_}@); +\end{codeblock} +\end{itemdescr} + +\begin{itemdecl} +constexpr @\exposid{iterator}@& operator++(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +@\exposid{tuple-for-each}@([](auto& i) { ++i; }, @\exposid{current_}@); +return *this; +\end{codeblock} +\end{itemdescr} + +\begin{itemdecl} +constexpr void operator++(int); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to \tcode{++*this}. +\end{itemdescr} + +\begin{itemdecl} +constexpr @\exposid{iterator}@ operator++(int) requires @\exposconcept{all-forward}@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +auto tmp = *this; +++*this; +return tmp; +\end{codeblock} +\end{itemdescr} + +\begin{itemdecl} +constexpr @\exposid{iterator}@& operator--() requires @\exposconcept{all-bidirectional}@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +@\exposid{tuple-for-each}@([](auto& i) { --i; }, @\exposid{current_}@); +return *this; +\end{codeblock} +\end{itemdescr} + +\begin{itemdecl} +constexpr @\exposid{iterator}@ operator--(int) requires @\exposconcept{all-bidirectional}@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +auto tmp = *this; +--*this; +return tmp; +\end{codeblock} +\end{itemdescr} + +\begin{itemdecl} +constexpr @\exposid{iterator}@& operator+=(difference_type x) + requires @\exposconcept{all-random-access}@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +@\exposid{tuple-for-each}@([&](I& i) { i += iter_difference_t(x); }, @\exposid{current_}@); +return *this; +\end{codeblock} +\end{itemdescr} + +\begin{itemdecl} +constexpr @\exposid{iterator}@& operator-=(difference_type x) + requires @\exposconcept{all-random-access}@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +@\exposid{tuple-for-each}@([&](I& i) { i -= iter_difference_t(x); }, @\exposid{current_}@); +return *this; +\end{codeblock} +\end{itemdescr} + +\begin{itemdecl} +constexpr auto operator[](difference_type n) const + requires @\exposconcept{all-random-access}@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +return @\exposid{tuple-transform}@([&](I& i) -> decltype(auto) { + return i[iter_difference_t(n)]; +}, @\exposid{current_}@); +\end{codeblock} +\end{itemdescr} + +\begin{itemdecl} +friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires (@\libconcept{equality_comparable}@>> && ...); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\begin{itemize} +\item +\tcode{x.\exposid{current_} == y.\exposid{current_}} +if \tcode{\exposconcept{all-bidirectional}} is \tcode{true}. +\item +Otherwise, \tcode{true} +if there exists an integer $0 \leq i < \tcode{sizeof...(Views)}$ +such that \tcode{bool(std::\brk{}get<$i$>(x.\exposid{current_}) == +std::get<$i$>(y.\exposid{current_}))} is \tcode{true}. +\begin{note} +This allows \tcode{zip_view} to model \libconcept{common_range} +when all constituent views model \libconcept{common_range}. +\end{note} +\item +Otherwise, \tcode{false}. +\end{itemize} +\end{itemdescr} + +\begin{itemdecl} +friend constexpr bool operator<(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\exposconcept{all-random-access}@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{x.\exposid{current_} < y.\exposid{current_}}. +\end{itemdescr} + +\begin{itemdecl} +friend constexpr bool operator>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\exposconcept{all-random-access}@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return y < x;} +\end{itemdescr} + +\begin{itemdecl} +friend constexpr bool operator<=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\exposconcept{all-random-access}@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return !(y < x);} +\end{itemdescr} + +\begin{itemdecl} +friend constexpr bool operator>=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\exposconcept{all-random-access}@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return !(x < y);} +\end{itemdescr} + +\begin{itemdecl} +friend constexpr auto operator<=>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\exposconcept{all-random-access}@ && + (@\libconcept{three_way_comparable}@>> && ...); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{x.\exposid{current_} <=> y.\exposid{current_}}. +\end{itemdescr} + +\begin{itemdecl} +friend constexpr @\exposid{iterator}@ operator+(const @\exposid{iterator}@& i, difference_type n) + requires @\exposconcept{all-random-access}@; +friend constexpr @\exposid{iterator}@ operator+(difference_type n, const @\exposid{iterator}@& i) + requires @\exposconcept{all-random-access}@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +auto r = i; +r += n; +return r; +\end{codeblock} +\end{itemdescr} + +\begin{itemdecl} +friend constexpr @\exposid{iterator}@ operator-(const @\exposid{iterator}@& i, difference_type n) + requires @\exposconcept{all-random-access}@; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +auto r = i; +r -= n; +return r; +\end{codeblock} +\end{itemdescr} + +\begin{itemdecl} +friend constexpr difference_type operator-(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires (@\libconcept{sized_sentinel_for}@>, + iterator_t<@\exposid{maybe-const}@>> && ...); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \tcode{\exposid{DIST}($i$)} be \tcode{difference_type(std::get<$i$>(x.\exposid{current_}) - std::get<$i$>(y.\exposid{current_}))}. + +\pnum +\returns +The value with the smallest absolute value among \tcode{\exposid{DIST}($n$)} +for all integers $0 \leq n < \tcode{sizeof...(Views)}$. +\end{itemdescr} + +\begin{itemdecl} +friend constexpr auto iter_move(const @\exposid{iterator}@& i) noexcept(@\seebelow@); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +return @\exposid{tuple-transform}@(ranges::iter_move, i.@\exposid{current_}@); +\end{codeblock} + +\pnum +\remarks +The exception specification is equivalent to: +\begin{codeblock} +(noexcept(ranges::iter_move(declval>&>())) && ...) && +(is_nothrow_move_constructible_v>> && ...) +\end{codeblock} +\end{itemdescr} + +\begin{itemdecl} +friend constexpr void iter_swap(const @\exposid{iterator}@& l, const @\exposid{iterator}@& r) noexcept(@\seebelow@) + requires (@\libconcept{indirectly_swappable}@>> && ...); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +For every integer $0 \leq i < \tcode{sizeof...(Views)}$, +performs: +\begin{codeblock} +ranges::iter_swap(std::get<@$i$@>(l.@\exposid{current_}@), std::get<@$i$@>(r.@\exposid{current_}@)) +\end{codeblock} + +\pnum +\remarks +The exception specification is equivalent to +the logical \logop{AND} of the following expressions: +\begin{codeblock} +noexcept(ranges::iter_swap(std::get<@$i$@>(l.@\exposid{current_}@), std::get<@$i$@>(r.@\exposid{current_}@))) +\end{codeblock} +for every integer $0 \leq i < \tcode{sizeof...(Views)}$. +\end{itemdescr} + +\rSec3[range.zip.sentinel]{Class template \tcode{zip_view::\exposid{sentinel}}} + +\indexlibraryglobal{zip_view::sentinel}% +\begin{codeblock} +namespace std::ranges { + template<@\libconcept{input_range}@... Views> + requires (@\libconcept{view}@ && ...) && (sizeof...(Views) > 0) + template + class zip_view::@\exposid{sentinel}@ { + @\exposid{tuple-or-pair}@>...> @\exposid{end_}@; // \expos + constexpr explicit @\exposid{sentinel}@(@\exposid{tuple-or-pair}@>...> end); + // \expos + public: + @\exposid{sentinel}@() = default; + constexpr @\exposid{sentinel}@(@\exposid{sentinel}@ i) + requires Const && + (@\libconcept{convertible_to}@, sentinel_t<@\exposid{maybe-const}@>> && ...); + + template + requires (@\libconcept{sentinel_for}@>, + iterator_t<@\exposid{maybe-const}@>> && ...) + friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); + + template + requires (@\libconcept{sized_sentinel_for}@>, + iterator_t<@\exposid{maybe-const}@>> && ...) + friend constexpr common_type_t>...> + operator-(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); + + template + requires (@\libconcept{sized_sentinel_for}@>, + iterator_t<@\exposid{maybe-const}@>> && ...) + friend constexpr common_type_t>...> + operator-(const @\exposid{sentinel}@& y, const @\exposid{iterator}@& x); + }; +} +\end{codeblock} + +\begin{itemdecl} +constexpr explicit @\exposid{sentinel}@(@\exposid{tuple-or-pair}@>...> end); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \exposid{end_} with \tcode{end}. +\end{itemdescr} + +\begin{itemdecl} +constexpr @\exposid{sentinel}@(@\exposid{sentinel}@ i) + requires Const && + (@\libconcept{convertible_to}@, sentinel_t<@\exposid{maybe-const}@>> && ...); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \exposid{end_} with \tcode{std::move(i.\exposid{end_})}. +\end{itemdescr} + +\begin{itemdecl} +template + requires (@\libconcept{sentinel_for}@>, + iterator_t>> && ...) +friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{true} if there exists an integer $0 \leq i < \tcode{sizeof...(Views)}$ +such that \tcode{bool(std::get<$i$>(x.\brk{}\exposid{current_}) == +std::get<$i$>(y.\exposid{end_}))} is \tcode{true}. +Otherwise, \tcode{false}. +\end{itemdescr} + +\begin{itemdecl} +template + requires (@\libconcept{sized_sentinel_for}@>, + iterator_t<@\exposid{maybe-const}@>> && ...) +friend constexpr common_type_t>...> + operator-(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \tcode{D} be the return type. +Let \tcode{\exposid{DIST}($i$)} be +\tcode{D(std::get<$i$>(x.\exposid{current_}) - std::get<$i$>(y.\exposid{end_}))}. + +\pnum +\returns +The value with the smallest absolute value among \tcode{\exposid{DIST}($n$)} +for all integers $0 \leq n < \tcode{sizeof...(Views)}$. +\end{itemdescr} + +\begin{itemdecl} +template + requires (@\libconcept{sized_sentinel_for}@>, + iterator_t<@\exposid{maybe-const}@>> && ...) +friend constexpr common_type_t>...> + operator-(const @\exposid{sentinel}@& y, const @\exposid{iterator}@& x); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to \tcode{return -(x - y);} +\end{itemdescr} + +\rSec2[range.zip.transform]{Zip transform view} + +\rSec3[range.zip.transform.overview]{Overview} + +\pnum +\indexlibraryglobal{zip_transform_view}% +\tcode{zip_transform_view} takes an invocable object and +any number of \libconcept{view}s and +produces a \libconcept{view} +whose $M^\text{th}$ element is +the result of applying the invocable object +to the $M^\text{th}$ elements of all views. + +\pnum +\indexlibrarymember{zip_transform}{views}% +The name \tcode{views::zip_transform} denotes +a customization point object\iref{customization.point.object}. +Let \tcode{F} be a subexpression, and +let \tcode{Es...} be a pack of subexpressions. +\begin{itemize} +\item +If \tcode{Es} is an empty pack, +let \tcode{FD} be \tcode{decay_t}. +\begin{itemize} +\item +If \tcode{\libconcept{copy_constructible} \&\& +\libconcept{regular_invocable}} is \tcode{false}, or +if \tcode{decay_t>} is not an object type, +\tcode{views::zip_transform(F, Es...)} is ill-formed. +\item +Otherwise, the expression \tcode{views::zip_transform(F, Es...)} +is expression-equivalent to +\begin{codeblock} +((void)F, auto(views::empty>>)) +\end{codeblock} +\end{itemize} +\item +Otherwise, the expression \tcode{views::zip_transform(F, Es...)} +is expression-equivalent to \tcode{zip_trans\-form_view(F, Es...)}. +\end{itemize} + +\pnum +\begin{example} +\begin{codeblock} +vector v1 = {1, 2}; +vector v2 = {4, 5, 6}; + +for (auto i : views::zip_transform(plus(), v1, v2)) { + cout << i << ' '; // prints: 5 7 +} +\end{codeblock} +\end{example} + +\rSec3[range.zip.transform.view]{Class template \tcode{zip_transform_view}} + +\indexlibrarymember{begin}{zip_transform_view}% +\indexlibrarymember{end}{zip_transform_view}% +\indexlibrarymember{size}{zip_transform_view}% +\begin{codeblock} +namespace std::ranges { + template<@\libconcept{copy_constructible}@ F, @\libconcept{input_range}@... Views> + requires (@\libconcept{view}@ && ...) && (sizeof...(Views) > 0) && is_object_v && + @\libconcept{regular_invocable}@...> && + @\exposconcept{can-reference}@...>> + class zip_transform_view : public view_interface> { + @\exposid{copyable-box}@ @\exposid{fun_}@; // \expos + zip_view @\exposid{zip_}@; // \expos + + using @\exposid{InnerView}@ = zip_view; // \expos + template + using @\exposid{ziperator}@ = iterator_t<@\exposid{maybe-const}@>; // \expos + template + using @\exposid{zentinel}@ = sentinel_t<@\exposid{maybe-const}@>; // \expos + + // \ref{range.zip.transform.iterator}, class template \tcode{zip_transform_view::\exposid{iterator}} + template class @\exposid{iterator}@; // \expos + // \ref{range.zip.transform.sentinel}, class template \tcode{zip_transform_view::\exposid{sentinel}} + template class @\exposid{sentinel}@; // \expos + + public: + zip_transform_view() = default; + + constexpr explicit zip_transform_view(F fun, Views... views); + + constexpr auto begin() { + return @\exposid{iterator}@(*this, @\exposid{zip_}@.begin()); + } + + constexpr auto begin() const + requires @\libconcept{range}@ && + @\libconcept{regular_invocable}@...> { + return @\exposid{iterator}@(*this, @\exposid{zip_}@.begin()); + } + + constexpr auto end() { + if constexpr (@\libconcept{common_range}@<@\exposid{InnerView}@>) { + return @\exposid{iterator}@(*this, @\exposid{zip_}@.end()); + } else { + return @\exposid{sentinel}@(@\exposid{zip_}@.end()); + } + } + + constexpr auto end() const + requires @\libconcept{range}@ && + @\libconcept{regular_invocable}@...> { + if constexpr (@\libconcept{common_range}@) { + return @\exposid{iterator}@(*this, @\exposid{zip_}@.end()); + } else { + return @\exposid{sentinel}@(@\exposid{zip_}@.end()); + } + } + + constexpr auto size() requires @\libconcept{sized_range}@<@\exposid{InnerView}@> { + return @\exposid{zip_}@.size(); + } + + constexpr auto size() const requires @\libconcept{sized_range}@ { + return @\exposid{zip_}@.size(); + } + }; + + template + zip_transform_view(F, Rs&&...) -> zip_transform_view...>; +} +\end{codeblock} + +\begin{itemdecl} +constexpr explicit zip_transform_view(F fun, Views... views); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \exposid{fun_} with \tcode{std::move(fun)} and +\exposid{zip_} with \tcode{std::move(views)...}. +\end{itemdescr} + +\rSec3[range.zip.transform.iterator]{Class template \tcode{zip_transform_view::\exposid{iterator}}} + +\indexlibraryglobal{zip_transform_view::iterator}% +\begin{codeblock} +namespace std::ranges { + template<@\libconcept{copy_constructible}@ F, @\libconcept{input_range}@... Views> + requires (@\libconcept{view}@ && ...) && (sizeof...(Views) > 0) && is_object_v && + @\libconcept{regular_invocable}@...> && + @\exposconcept{can-reference}@...>> + template + class zip_transform_view::@\exposid{iterator}@ { + using @\exposid{Parent}@ = @\exposid{maybe-const}@; // \expos + using @\exposid{Base}@ = @\exposid{maybe-const}@; // \expos + @\exposid{Parent}@* @\exposid{parent_}@ = nullptr; // \expos + @\exposid{ziperator}@ @\exposid{inner_}@; // \expos + + constexpr @\exposid{iterator}@(@\exposid{Parent}@& parent, @\exposid{ziperator}@ inner); // \expos + + public: + using iterator_category = @\seebelow@; // not always present + using iterator_concept = typename @\exposid{ziperator}@::iterator_concept; + using value_type = + remove_cvref_t&, + range_reference_t<@\exposid{maybe-const}@>...>>; + using difference_type = range_difference_t<@\exposid{Base}@>; + + @\exposid{iterator}@() = default; + constexpr @\exposid{iterator}@(@\exposid{iterator}@ i) + requires Const && @\libconcept{convertible_to}@<@\exposid{ziperator}@, @\exposid{ziperator}@>; + + constexpr decltype(auto) operator*() const noexcept(@\seebelow@); + constexpr @\exposid{iterator}@& operator++(); + constexpr void operator++(int); + constexpr @\exposid{iterator}@ operator++(int) requires @\libconcept{forward_range}@<@\exposid{Base}@>; + + constexpr @\exposid{iterator}@& operator--() requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>; + constexpr @\exposid{iterator}@ operator--(int) requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>; + + constexpr @\exposid{iterator}@& operator+=(difference_type x) requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + constexpr @\exposid{iterator}@& operator-=(difference_type x) requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + + constexpr decltype(auto) operator[](difference_type n) const + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + + friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{equality_comparable}@<@\exposid{ziperator}@>; + + friend constexpr bool operator<(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + friend constexpr bool operator>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + friend constexpr bool operator<=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + friend constexpr bool operator>=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + friend constexpr auto operator<=>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@> && @\libconcept{three_way_comparable}@<@\exposid{ziperator}@>; + + friend constexpr @\exposid{iterator}@ operator+(const @\exposid{iterator}@& i, difference_type n) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + friend constexpr @\exposid{iterator}@ operator+(difference_type n, const @\exposid{iterator}@& i) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + friend constexpr @\exposid{iterator}@ operator-(const @\exposid{iterator}@& i, difference_type n) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + friend constexpr difference_type operator-(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{sized_sentinel_for}@<@\exposid{ziperator}@, @\exposid{ziperator}@>; + }; +} +\end{codeblock} + +\pnum +The member \grammarterm{typedef-name} +\tcode{\exposid{iterator}::iterator_category} +is defined if and only if \exposid{Base} models \libconcept{forward_range}. +In that case, +\tcode{\exposid{iterator}::iterator_category} is defined as follows: +\begin{itemize} +\item +If +\begin{codeblock} +invoke_result_t<@\exposid{maybe-const}@&, range_reference_t<@\exposid{maybe-const}@>...> +\end{codeblock} +is not an lvalue reference, +\tcode{iterator_category} denotes \tcode{input_iterator_tag}. +\item +Otherwise, let \tcode{Cs} denote the pack of types +\tcode{iterator_traits>>::iterator_category...}. +\begin{itemize} +\item +If \tcode{(\libconcept{derived_from} \&\& ...)} +is \tcode{true}, +\tcode{iterator_category} denotes \tcode{random_access_iterator_tag}. +\item +Otherwise, +if \tcode{(\libconcept{derived_from} \&\& ...)} +is \tcode{true}, +\tcode{itera\-tor_category} denotes \tcode{bidirectional_iterator_tag}. +\item +Otherwise, +if \tcode{(\libconcept{derived_from} \&\& ...)} +is \tcode{true}, +\tcode{iterator_cate\-gory} denotes \tcode{forward_iterator_tag}. +\item +Otherwise, \tcode{iterator_category} denotes \tcode{input_iterator_tag}. +\end{itemize} +\end{itemize} + +\begin{itemdecl} +constexpr @\exposid{iterator}@(@\exposid{Parent}@& parent, @\exposid{ziperator}@ inner); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \exposid{parent_} with \tcode{addressof(parent)} and +\exposid{inner_} with \tcode{std::move(inner)}. +\end{itemdescr} + +\begin{itemdecl} +constexpr @\exposid{iterator}@(@\exposid{iterator}@ i) + requires Const && @\libconcept{convertible_to}@<@\exposid{ziperator}@, @\exposid{ziperator}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \exposid{parent_} with \tcode{i.\exposid{parent_}} and +\exposid{inner_} with \tcode{std::move(i.\exposid{inner_})}. +\end{itemdescr} + +\begin{itemdecl} +constexpr decltype(auto) operator*() const noexcept(@\seebelow@); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +return apply([&](const auto&... iters) -> decltype(auto) { + return invoke(*@\exposid{parent_}@->@\exposid{fun_}@, *iters...); +}, @\exposid{inner_}@.@\exposid{current_}@); +\end{codeblock} + +\pnum +\remarks +Let \tcode{Is} be the pack \tcode{0, 1, \ldots, \tcode{(sizeof...(Views)-1)}}. +The exception specification is equivalent to: +\tcode{noexcept(invoke(*\exposid{parent_}->\exposid{fun_}, *std::get(\exposid{inner_}.\exposid{current_})...))}. +\end{itemdescr} + +\begin{itemdecl} +constexpr @\exposid{iterator}@& operator++(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +++@\exposid{inner_}@; +return *this; +\end{codeblock} +\end{itemdescr} + +\begin{itemdecl} +constexpr void operator++(int); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{++*this}. +\end{itemdescr} + +\begin{itemdecl} +constexpr @\exposid{iterator}@ operator++(int) requires @\libconcept{forward_range}@<@\exposid{Base}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +auto tmp = *this; +++*this; +return tmp; +\end{codeblock} +\end{itemdescr} + +\begin{itemdecl} +constexpr @\exposid{iterator}@& operator--() requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +--@\exposid{inner_}@; +return *this; +\end{codeblock} +\end{itemdescr} + +\begin{itemdecl} +constexpr @\exposid{iterator}@ operator--(int) requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +auto tmp = *this; +--*this; +return tmp; +\end{codeblock} +\end{itemdescr} + +\begin{itemdecl} +constexpr @\exposid{iterator}@& operator+=(difference_type x) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +@\exposid{inner_}@ += x; +return *this; +\end{codeblock} +\end{itemdescr} + +\begin{itemdecl} +constexpr @\exposid{iterator}@& operator-=(difference_type x) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +@\exposid{inner_}@ -= x; +return *this; +\end{codeblock} +\end{itemdescr} + +\begin{itemdecl} +constexpr decltype(auto) operator[](difference_type n) const + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +return apply([&](const Is&... iters) -> decltype(auto) { + return invoke(*@\exposid{parent_}@->@\exposid{fun_}@, iters[iter_difference_t(n)]...); +}, @\exposid{inner_}@.@\exposid{current_}@); +\end{codeblock} +\end{itemdescr} + +\begin{itemdecl} +friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{equality_comparable}@<@\exposid{ziperator}@>; +friend constexpr bool operator<(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +friend constexpr bool operator>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +friend constexpr bool operator<=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +friend constexpr bool operator>=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +friend constexpr auto operator<=>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@> && @\libconcept{three_way_comparable}@<@\exposid{ziperator}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \placeholder{op} be the operator. + +\pnum +\effects +Equivalent to: +\tcode{return x.\exposid{inner_} \placeholder{op} y.\exposid{inner_};} +\end{itemdescr} + +\begin{itemdecl} +friend constexpr @\exposid{iterator}@ operator+(const @\exposid{iterator}@& i, difference_type n) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +friend constexpr @\exposid{iterator}@ operator+(difference_type n, const @\exposid{iterator}@& i) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\tcode{return \exposid{iterator}(*i.\exposid{parent_}, i.\exposid{inner_} + n);} +\end{itemdescr} + +\begin{itemdecl} +friend constexpr @\exposid{iterator}@ operator-(const @\exposid{iterator}@& i, difference_type n) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\tcode{return \exposid{iterator}(*i.\exposid{parent_}, i.\exposid{inner_} - n);} +\end{itemdescr} + +\begin{itemdecl} +friend constexpr difference_type operator-(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{sized_sentinel_for}@<@\exposid{ziperator}@, @\exposid{ziperator}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\tcode{return x.\exposid{inner_} - y.\exposid{inner_};} +\end{itemdescr} + +\rSec3[range.zip.transform.sentinel]{Class template \tcode{zip_transform_view::\exposid{sentinel}}} + +\indexlibraryglobal{zip_transform_view::sentinel}% +\begin{codeblock} +namespace std::ranges { + template<@\libconcept{copy_constructible}@ F, @\libconcept{input_range}@... Views> + requires (@\libconcept{view}@ && ...) && (sizeof...(Views) > 0) && is_object_v && + @\libconcept{regular_invocable}@...> && + @\exposconcept{can-reference}@...>> + template + class zip_transform_view::@\exposid{sentinel}@ { + @\exposid{zentinel}@ @\exposid{inner_}@; // \expos + constexpr explicit @\exposid{sentinel}@(@\exposid{zentinel}@ inner); // \expos + public: + @\exposid{sentinel}@() = default; + constexpr @\exposid{sentinel}@(@\exposid{sentinel}@ i) + requires Const && @\libconcept{convertible_to}@<@\exposid{zentinel}@, @\exposid{zentinel}@>; + + template + requires @\libconcept{sentinel_for}@<@\exposid{zentinel}@, @\exposid{ziperator}@> + friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); + + template + requires @\libconcept{sized_sentinel_for}@<@\exposid{zentinel}@, @\exposid{ziperator}@> + friend constexpr range_difference_t<@\exposid{maybe-const}@> + operator-(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); + + template + requires @\libconcept{sized_sentinel_for}@<@\exposid{zentinel}@, @\exposid{ziperator}@> + friend constexpr range_difference_t<@\exposid{maybe-const}@> + operator-(const @\exposid{sentinel}@& x, const @\exposid{iterator}@& y); + }; +} +\end{codeblock} + +\begin{itemdecl} +constexpr explicit @\exposid{sentinel}@(@\exposid{zentinel}@ inner); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \exposid{inner_} with \tcode{inner}. +\end{itemdescr} + +\begin{itemdecl} +constexpr @\exposid{sentinel}@(@\exposid{sentinel}@ i) + requires Const && @\libconcept{convertible_to}@<@\exposid{zentinel}@, @\exposid{zentinel}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \exposid{inner_} with \tcode{std::move(i.\exposid{inner_})}. +\end{itemdescr} + +\begin{itemdecl} +template + requires @\libconcept{sentinel_for}@<@\exposid{zentinel}@, @\exposid{ziperator}@> +friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return x.\exposid{inner_} == y.\exposid{inner_};} +\end{itemdescr} + +\begin{itemdecl} +template + requires @\libconcept{sized_sentinel_for}@<@\exposid{zentinel}@, @\exposid{ziperator}@> +friend constexpr range_difference_t<@\exposid{maybe-const}@> + operator-(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); +template + requires @\libconcept{sized_sentinel_for}@<@\exposid{zentinel}@, @\exposid{ziperator}@> +friend constexpr range_difference_t<@\exposid{maybe-const}@> + operator-(const @\exposid{sentinel}@& x, const @\exposid{iterator}@& y); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return x.\exposid{inner_} - y.\exposid{inner_};} +\end{itemdescr} + +\rSec2[range.adjacent]{Adjacent view} + +\rSec3[range.adjacent.overview]{Overview} + +\pnum +\indexlibraryglobal{adjacent_view}% +\tcode{adjacent_view} takes a \libconcept{view} and +produces a \libconcept{view} whose $M^\text{th}$ element is +a tuple of references to +the $M^\text{th}$ through $(M + N - 1)^\text{th}$ elements of +the original view. +If the original view has fewer than $N$ elements, the resulting view is empty. + +\pnum +\indexlibrarymember{adjacent}{views}% +The name \tcode{views::adjacent} denotes +a range adaptor object\iref{range.adaptor.object}. +Given a subexpression \tcode{E} and a constant expression \tcode{N}, +the expression \tcode{views::adjacent(E)} is expression-equivalent to +\begin{itemize} +\item +\tcode{((void)E, auto(views::empty>))} +if \tcode{N} is equal to \tcode{0}, +\item +otherwise, \tcode{adjacent_view, N>(E)}. +\end{itemize} + +\begin{example} +\begin{codeblock} +vector v = {1, 2, 3, 4}; + +for (auto i : v | views::adjacent<2>) { + cout << '(' << i.first << ', ' << i.second << ") "; // prints: (1, 2) (2, 3) (3, 4) +} +\end{codeblock} +\end{example} + +\pnum +Define \tcode{\exposid{REPEAT}(T, N)} as a pack of \tcode{N} types, +each of which denotes the same type as \tcode{T}. + +\rSec3[range.adjacent.view]{Class template \tcode{adjacent_view}} + +\indexlibrarymember{begin}{adjacent_view}% +\indexlibrarymember{end}{adjacent_view}% +\indexlibrarymember{size}{adjacent_view}% +\begin{codeblock} +namespace std::ranges { + template<@\libconcept{forward_range}@ V, size_t N> + requires @\libconcept{view}@ && (N > 0) + class adjacent_view : public view_interface> { + V @\exposid{base_}@ = V(); // \expos + + // \ref{range.adjacent.iterator}, class template \tcode{adjacent_view::\exposid{iterator}} + template class @\exposid{iterator}@; // \expos + // \ref{range.adjacent.sentinel}, class template \tcode{adjacent_view::\exposid{sentinel}} + template class @\exposid{sentinel}@; // \expos + + struct @\exposid{as-sentinel}@{}; // \expos + + public: + adjacent_view() requires @\libconcept{default_initializable}@ = default; + constexpr explicit adjacent_view(V base); + + constexpr auto begin() requires (!@\exposconcept{simple-view}@) { + return @\exposid{iterator}@(ranges::begin(@\exposid{base_}@), ranges::end(@\exposid{base_}@)); + } + + constexpr auto begin() const requires @\libconcept{range}@ { + return @\exposid{iterator}@(ranges::begin(@\exposid{base_}@), ranges::end(@\exposid{base_}@)); + } + + constexpr auto end() requires (!@\exposconcept{simple-view}@) { + if constexpr (@\libconcept{common_range}@) { + return @\exposid{iterator}@(@\exposid{as-sentinel}@{}, ranges::begin(@\exposid{base_}@), ranges::end(@\exposid{base_}@)); + } else { + return @\exposid{sentinel}@(ranges::end(@\exposid{base_}@)); + } + } + + constexpr auto end() const requires @\libconcept{range}@ { + if constexpr (@\libconcept{common_range}@) { + return @\exposid{iterator}@(@\exposid{as-sentinel}@{}, ranges::begin(@\exposid{base_}@), ranges::end(@\exposid{base_}@)); + } else { + return @\exposid{sentinel}@(ranges::end(@\exposid{base_}@)); + } + } + + constexpr auto size() requires @\libconcept{sized_range}@; + constexpr auto size() const requires @\libconcept{sized_range}@; + }; +} +\end{codeblock} + +\begin{itemdecl} +constexpr explicit adjacent_view(V base); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \exposid{base_} with \tcode{std::move(base)}. +\end{itemdescr} + +\begin{itemdecl} +constexpr auto size() requires @\libconcept{sized_range}@; +constexpr auto size() const requires @\libconcept{sized_range}@; +\end{itemdecl} + +\begin{itemdescr} +\effects +Equivalent to: +\begin{codeblock} +using ST = decltype(ranges::size(@\exposid{base_}@)); +using CT = common_type_t; +auto sz = static_cast(ranges::size(@\exposid{base_}@)); +sz -= std::min(sz, N - 1); +return static_cast(sz); +\end{codeblock} +\end{itemdescr} + +\rSec3[range.adjacent.iterator]{Class template \tcode{adjacent_view::\exposid{iterator}}} + +\indexlibraryglobal{adjacent_view::iterator}% +\begin{codeblock} +namespace std::ranges { + template<@\libconcept{forward_range}@ V, size_t N> + requires @\libconcept{view}@ && (N > 0) + template + class adjacent_view::@\exposid{iterator}@ { + using @\exposid{Base}@ = @\exposid{maybe-const}@; // \expos + array, N> @\exposid{current_}@ = array, N>(); // \expos + constexpr @\exposid{iterator}@(iterator_t<@\exposid{Base}@> first, sentinel_t<@\exposid{Base}@> last); // \expos + constexpr @\exposid{iterator}@(@\exposid{as-sentinel}@, iterator_t<@\exposid{Base}@> first, iterator_t<@\exposid{Base}@> last); + // \expos + public: + using iterator_category = input_iterator_tag; + using iterator_concept = @\seebelow@; + using value_type = @\exposid{tuple-or-pair}@<@\exposid{REPEAT}@(range_value_t<@\exposid{Base}@>, N)...>; + using difference_type = range_difference_t<@\exposid{Base}@>; + + @\exposid{iterator}@() = default; + constexpr @\exposid{iterator}@(@\exposid{iterator}@ i) + requires Const && @\libconcept{convertible_to}@, iterator_t<@\exposid{Base}@>>; + + constexpr auto operator*() const; + constexpr @\exposid{iterator}@& operator++(); + constexpr @\exposid{iterator}@ operator++(int); + + constexpr @\exposid{iterator}@& operator--() requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>; + constexpr @\exposid{iterator}@ operator--(int) requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>; + + constexpr @\exposid{iterator}@& operator+=(difference_type x) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + constexpr @\exposid{iterator}@& operator-=(difference_type x) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + + constexpr auto operator[](difference_type n) const + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + + friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y); + friend constexpr bool operator<(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + friend constexpr bool operator>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + friend constexpr bool operator<=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + friend constexpr bool operator>=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + friend constexpr auto operator<=>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@> && + @\libconcept{three_way_comparable}@>; + + friend constexpr @\exposid{iterator}@ operator+(const @\exposid{iterator}@& i, difference_type n) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + friend constexpr @\exposid{iterator}@ operator+(difference_type n, const @\exposid{iterator}@& i) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + friend constexpr @\exposid{iterator}@ operator-(const @\exposid{iterator}@& i, difference_type n) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + friend constexpr difference_type operator-(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{sized_sentinel_for}@, iterator_t<@\exposid{Base}@>>; + + friend constexpr auto iter_move(const @\exposid{iterator}@& i) noexcept(@\seebelow@); + friend constexpr void iter_swap(const @\exposid{iterator}@& l, const @\exposid{iterator}@& r) noexcept(@\seebelow@) + requires @\libconcept{indirectly_swappable}@>; + }; +} +\end{codeblock} + +\pnum +\tcode{\exposid{iterator}::iterator_concept} is defined as follows: +\begin{itemize} +\item +If \exposid{Base} models \libconcept{random_access_range}, +then \tcode{iterator_concept} denotes \tcode{random_access_iterator_tag}. +\item +Otherwise, if \exposid{Base} models \libconcept{bidirectional_range}, +then \tcode{iterator_concept} denotes \tcode{bidirectional_iterator_tag}. +\item +Otherwise, \tcode{iterator_concept} denotes \tcode{forward_iterator_tag}. +\end{itemize} + +\pnum +If the invocation of any non-const member function of \exposid{iterator} +exits via an exception, the \exposid{iterator} acquires a singular value. + +\begin{itemdecl} +constexpr @\exposid{iterator}@(iterator_t<@\exposid{Base}@> first, sentinel_t<@\exposid{Base}@> last); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\ensures +\tcode{\exposid{current_}[0] == first} is \tcode{true}, and +for every integer $1 \leq i < \tcode{N}$, +\tcode{\exposid{current_}[$i$] == ranges::next(\exposid{current_}[$i$-1], 1, last)} +is \tcode{true}. +\end{itemdescr} + +\begin{itemdecl} +constexpr @\exposid{iterator}@(@\exposid{as-sentinel}@, iterator_t<@\exposid{Base}@> first, iterator_t<@\exposid{Base}@> last); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\ensures +If \exposid{Base} does not model \libconcept{bidirectional_range}, +each element of \exposid{current_} is equal to \exposid{last}. +Otherwise, \tcode{\exposid{current_}[N-1] == last} is \tcode{true}, and +for every integer $0 \leq i < (\tcode{N} - 1)$, +\tcode{\exposid{current_}[$i$] == ranges::prev(\exposid{current_}[$i$+1], 1, first)} +is \tcode{true}. +\end{itemdescr} + +\begin{itemdecl} +constexpr @\exposid{iterator}@(@\exposid{iterator}@ i) + requires Const && @\libconcept{convertible_to}@, iterator_t<@\exposid{Base}@>>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes each element of \exposid{current_} +with the corresponding element of \tcode{i.\exposid{current_}} as an xvalue. +\end{itemdescr} + +\begin{itemdecl} +constexpr auto operator*() const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +return @\exposid{tuple-transform}@([](auto& i) -> decltype(auto) { return *i; }, @\exposid{current_}@); +\end{codeblock} +\end{itemdescr} + +\begin{itemdecl} +constexpr @\exposid{iterator}@& operator++(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{\exposid{current_}.back()} is incrementable. + +\pnum +\ensures +Each element of \exposid{current_} is equal to \tcode{ranges::next(i)}, +where \tcode{i} is the value of that element before the call. + +\pnum +\returns +\tcode{*this}. +\end{itemdescr} + +\begin{itemdecl} +constexpr @\exposid{iterator}@ operator++(int); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +Equivalent to: +\begin{codeblock} +auto tmp = *this; +++*this; +return tmp; +\end{codeblock} +\end{itemdescr} + +\begin{itemdecl} +constexpr @\exposid{iterator}@& operator--() requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{\exposid{current_}.front()} is decrementable. + +\pnum +\ensures +Each element of \exposid{current_} is equal to \tcode{ranges::prev(i)}, +where \tcode{i} is the value of that element before the call. + +\pnum +\returns +\tcode{*this}. +\end{itemdescr} + +\begin{itemdecl} +constexpr @\exposid{iterator}@ operator--(int) requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +auto tmp = *this; +--*this; +return tmp; +\end{codeblock} +\end{itemdescr} + +\begin{itemdecl} +constexpr @\exposid{iterator}@& operator+=(difference_type x) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{\exposid{current_}.back() + x} has well-defined behavior. + +\pnum +\ensures +Each element of \exposid{current_} is equal to \tcode{i + x}, +where \tcode{i} is the value of that element before the call. + +\pnum +\returns +\tcode{*this}. +\end{itemdescr} + +\begin{itemdecl} +constexpr @\exposid{iterator}@& operator-=(difference_type x) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{\exposid{current_}.front() - x} has well-defined behavior. + +\pnum +\ensures +Each element of \exposid{current_} is equal to \tcode{i - x}, +where \tcode{i} is the value of that element before the call. + +\pnum +\returns +\tcode{*this}. +\end{itemdescr} + +\begin{itemdecl} +constexpr auto operator[](difference_type n) const + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +return @\exposid{tuple-transform}@([&](auto& i) -> decltype(auto) { return i[n]; }, @\exposid{current_}@); +\end{codeblock} +\end{itemdescr} + +\begin{itemdecl} +friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{x.\exposid{current_}.back() == y.\exposid{current_}.back()}. +\end{itemdescr} + +\begin{itemdecl} +friend constexpr bool operator<(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{x.\exposid{current_}.back() < y.\exposid{current_}.back()}. +\end{itemdescr} + +\begin{itemdecl} +friend constexpr bool operator>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return y < x;} +\end{itemdescr} + +\begin{itemdecl} +friend constexpr bool operator<=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return !(y < x);} +\end{itemdescr} + +\begin{itemdecl} +friend constexpr bool operator>=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return !(x < y);} +\end{itemdescr} + +\begin{itemdecl} +friend constexpr auto operator<=>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@> && + @\libconcept{three_way_comparable}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +\tcode{x.\exposid{current_}.back() <=> y.\exposid{current_}.back()}. +\end{itemdescr} + +\begin{itemdecl} +friend constexpr @\exposid{iterator}@ operator+(const @\exposid{iterator}@& i, difference_type n) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +friend constexpr @\exposid{iterator}@ operator+(difference_type n, const @\exposid{iterator}@& i) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +auto r = i; +r += n; +return r; +\end{codeblock} +\end{itemdescr} + +\begin{itemdecl} +friend constexpr @\exposid{iterator}@ operator-(const @\exposid{iterator}@& i, difference_type n) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +auto r = i; +r -= n; +return r; +\end{codeblock} +\end{itemdescr} + +\begin{itemdecl} +friend constexpr difference_type operator-(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{sized_sentinel_for}@, iterator_t<@\exposid{Base}@>>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\tcode{return x.\exposid{current_}.back() - y.\exposid{current_}.back();} +\end{itemdescr} + +\begin{itemdecl} +friend constexpr auto iter_move(const @\exposid{iterator}@& i) noexcept(@\seebelow@); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\tcode{return \exposid{tuple-transform}(ranges::iter_move, i.\exposid{current_});} + +\pnum +\remarks +The exception specification is equivalent to: +\begin{codeblock} +noexcept(ranges::iter_move(declval&>())) && +is_nothrow_move_constructible_v> +\end{codeblock} +\end{itemdescr} + +\begin{itemdecl} +friend constexpr void iter_swap(const @\exposid{iterator}@& l, const @\exposid{iterator}@& r) noexcept(@\seebelow@) + requires @\libconcept{indirectly_swappable}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +None of the iterators in \tcode{l.\exposid{current_}} is equal to +an iterator in \tcode{r.\exposid{current_}}. + +\pnum +\effects +For every integer $0 \leq i < \tcode{N}$, +performs +\tcode{ranges::iter_swap(l.\exposid{current_}[$i$], r.\exposid{current_}[$i$])}. + +\pnum +\remarks +The exception specification is equivalent to: +\begin{codeblock} +noexcept(ranges::iter_swap(declval>(), declval>())) +\end{codeblock} +\end{itemdescr} + +\rSec3[range.adjacent.sentinel]{Class template \tcode{adjacent_view::\exposid{sentinel}}} + +\indexlibraryglobal{adjacent_view::sentinel}% +\begin{codeblock} +namespace std::ranges { + template<@\libconcept{forward_range}@ V, size_t N> + requires @\libconcept{view}@ && (N > 0) + template + class adjacent_view::@\exposid{sentinel}@ { + using @\exposid{Base}@ = @\exposid{maybe-const}@; // \expos + sentinel_t<@\exposid{Base}@> @\exposid{end_}@ = sentinel_t<@\exposid{Base}@>(); // \expos + constexpr explicit @\exposid{sentinel}@(sentinel_t<@\exposid{Base}@> end); // \expos + + public: + @\exposid{sentinel}@() = default; + constexpr @\exposid{sentinel}@(@\exposid{sentinel}@ i) + requires Const && @\libconcept{convertible_to}@, sentinel_t<@\exposid{Base}@>>; + + template + requires @\libconcept{sentinel_for}@, iterator_t<@\exposid{maybe-const}@>> + friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); + + template + requires @\libconcept{sized_sentinel_for}@, iterator_t<@\exposid{maybe-const}@>> + friend constexpr range_difference_t<@\exposid{maybe-const}@> + operator-(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); + + template + requires @\libconcept{sized_sentinel_for}@, iterator_t<@\exposid{maybe-const}@>> + friend constexpr range_difference_t<@\exposid{maybe-const}@> + operator-(const @\exposid{sentinel}@& y, const @\exposid{iterator}@& x); + }; +} +\end{codeblock} + +\begin{itemdecl} +constexpr explicit @\exposid{sentinel}@(sentinel_t<@\exposid{Base}@> end); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \exposid{end_} with \tcode{end}. +\end{itemdescr} + +\begin{itemdecl} +constexpr @\exposid{sentinel}@(@\exposid{sentinel}@ i) + requires Const && @\libconcept{convertible_to}@, sentinel_t<@\exposid{Base}@>>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \exposid{end_} with \tcode{std::move(i.\exposid{end_})}. +\end{itemdescr} + +\begin{itemdecl} +template + requires @\libconcept{sentinel_for}@, iterator_t<@\exposid{maybe-const}@>> +friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return x.\exposid{current_}.back() == y.\exposid{end_};} +\end{itemdescr} + +\begin{itemdecl} +template + requires @\libconcept{sized_sentinel_for}@, iterator_t<@\exposid{maybe-const}@>> +friend constexpr range_difference_t<@\exposid{maybe-const}@> + operator-(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return x.\exposid{current_}.back() - y.\exposid{end_};} +\end{itemdescr} + +\begin{itemdecl} +template + requires @\libconcept{sized_sentinel_for}@, iterator_t<@\exposid{maybe-const}@>> +friend constexpr range_difference_t<@\exposid{maybe-const}@> + operator-(const @\exposid{sentinel}@& y, const @\exposid{iterator}@& x); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return y.\exposid{end_} - x.\exposid{current_}.back();} +\end{itemdescr} + +\rSec2[range.adjacent.transform]{Adjacent transform view} + +\rSec3[range.adjacent.transform.overview]{Overview} + +\pnum +\indexlibraryglobal{adjacent_transform_view}% +\tcode{adjacent_transform_view} takes an invocable object and +a \libconcept{view} and produces a \libconcept{view} +whose $M^\text{th}$ element is the result of applying the invocable object +to the $M^\text{th}$ through $(M + N - 1)^\text{th}$ elements +of the original view. +If the original view has fewer than $N$ elements, the resulting view is empty. + +\pnum +\indexlibrarymember{adjacent_transform}{views}% +The name \tcode{views::adjacent_transform} denotes +a range adaptor object\iref{range.adaptor.object}. +Given subexpressions \tcode{E} and \tcode{F} and +a constant expression \tcode{N}: +\begin{itemize} +\item +If \tcode{N} is equal to \tcode{0}, +\tcode{views::adjacent_transform(E, F)} is expression-equivalent to +\tcode{((void)E, views::zip_transform(F))}, +except that the evaluations of \tcode{E} and \tcode{F} are +indeterminately sequenced. +\item +Otherwise, +the expression \tcode{views::adjacent_transform(E, F)} is +expression-equivalent to +\tcode{adja\-cent_transform_view, decay_t, N>(E, F)}. +\end{itemize} + +\pnum +\begin{example} +\begin{codeblock} +vector v = {1, 2, 3, 4}; + +for (auto i : v | views::adjacent_transform<2>(std::multiplies())) { + cout << i << ' '; // prints: 2 6 12 +} +\end{codeblock} +\end{example} + +\rSec3[range.adjacent.transform.view]{Class template \tcode{adjacent_transform_view}} + +\indexlibrarymember{begin}{adjacent_transform_view}% +\indexlibrarymember{end}{adjacent_transform_view}% +\indexlibrarymember{size}{adjacent_transform_view}% +\begin{codeblock} +namespace std::ranges { + template<@\libconcept{forward_range}@ V, @\libconcept{copy_constructible}@ F, size_t N> + requires @\libconcept{view}@ && (N > 0) && is_object_v && + @\libconcept{regular_invocable}@, N)...> && + @\exposconcept{can-reference}@, N)...>> + class adjacent_transform_view : public view_interface> { + @\exposid{copyable-box}@ @\exposid{fun_}@; // \expos + adjacent_view @\exposid{inner_}@; // \expos + + using @\exposid{InnerView}@ = adjacent_view; // \expos + template + using @\exposid{inner-iterator}@ = iterator_t<@\exposid{maybe-const}@>; // \expos + template + using @\exposid{inner-sentinel}@ = sentinel_t<@\exposid{maybe-const}@>; // \expos + + // \ref{range.adjacent.transform.iterator}, class template \tcode{adjacent_transform_view::\exposid{iterator}} + template class @\exposid{iterator}@; // \expos + // \ref{range.adjacent.transform.sentinel}, class template \tcode{adjacent_transform_view::\exposid{sentinel}} + template class @\exposid{sentinel}@; // \expos + + public: + adjacent_transform_view() = default; + constexpr explicit adjacent_transform_view(V base, F fun); + + constexpr auto begin() { + return @\exposid{iterator}@(*this, @\exposid{inner_}@.begin()); + } + + constexpr auto begin() const + requires @\libconcept{range}@ && + @\libconcept{regular_invocable}@, N)...> { + return @\exposid{iterator}@(*this, @\exposid{inner_}@.begin()); + } + + constexpr auto end() { + if constexpr (@\libconcept{common_range}@<@\exposid{InnerView}@>) { + return @\exposid{iterator}@(*this, @\exposid{inner_}@.end()); + } else { + return @\exposid{sentinel}@(@\exposid{inner_}@.end()); + } + } + + constexpr auto end() const + requires @\libconcept{range}@ && + @\libconcept{regular_invocable}@, N)...> { + if constexpr (@\libconcept{common_range}@) { + return @\exposid{iterator}@(*this, @\exposid{inner_}@.end()); + } else { + return @\exposid{sentinel}@(@\exposid{inner_}@.end()); + } + } + + constexpr auto size() requires @\libconcept{sized_range}@<@\exposid{InnerView}@> { + return @\exposid{inner_}@.size(); + } + + constexpr auto size() const requires @\libconcept{sized_range}@ { + return @\exposid{inner_}@.size(); + } + }; +} +\end{codeblock} + +\begin{itemdecl} +constexpr explicit adjacent_transform_view(V base, F fun); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \exposid{fun_} with \tcode{std::move(fun)} and +\exposid{inner_} with \tcode{std::move(base)}. +\end{itemdescr} + +\rSec3[range.adjacent.transform.iterator]{Class template \tcode{adjacent_transform_view::\exposid{iterator}}} + +\indexlibraryglobal{adjacent_transform_view::iterator}% +\begin{codeblock} +namespace std::ranges { + template<@\libconcept{forward_range}@ V, @\libconcept{copy_constructible}@ F, size_t N> + requires @\libconcept{view}@ && (N > 0) && is_object_v && + @\libconcept{regular_invocable}@, N)...> && + @\exposconcept{can-reference}@, N)...>> + template + class adjacent_transform_view::@\exposid{iterator}@ { + using @\exposid{Parent}@ = @\exposid{maybe-const}@; // \expos + using @\exposid{Base}@ = @\exposid{maybe-const}@; // \expos + @\exposid{Parent}@* @\exposid{parent_}@ = nullptr; // \expos + @\exposid{inner-iterator}@ @\exposid{inner_}@; // \expos + + constexpr @\exposid{iterator}@(@\exposid{Parent}@& parent, @\exposid{inner-iterator}@ inner); // \expos + + public: + using iterator_category = @\seebelow@; + using iterator_concept = typename @\exposid{inner-iterator}@::iterator_concept; + using value_type = + remove_cvref_t&, + @\exposid{REPEAT}@(range_reference_t<@\exposid{Base}@>, N)...>>; + using difference_type = range_difference_t<@\exposid{Base}@>; + + @\exposid{iterator}@() = default; + constexpr @\exposid{iterator}@(@\exposid{iterator}@ i) + requires Const && @\libconcept{convertible_to}@<@\exposid{inner-iterator}@, @\exposid{inner-iterator}@>; + + constexpr decltype(auto) operator*() const noexcept(@\seebelow@); + constexpr @\exposid{iterator}@& operator++(); + constexpr @\exposid{iterator}@ operator++(int); + constexpr @\exposid{iterator}@& operator--() requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>; + constexpr @\exposid{iterator}@ operator--(int) requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>; + constexpr @\exposid{iterator}@& operator+=(difference_type x) requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + constexpr @\exposid{iterator}@& operator-=(difference_type x) requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + + constexpr decltype(auto) operator[](difference_type n) const + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + + friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y); + friend constexpr bool operator<(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + friend constexpr bool operator>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + friend constexpr bool operator<=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires random_access_range; + friend constexpr bool operator>=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + friend constexpr auto operator<=>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@> && @\libconcept{three_way_comparable}@<@\exposid{inner-iterator}@>; + + friend constexpr @\exposid{iterator}@ operator+(const @\exposid{iterator}@& i, difference_type n) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + friend constexpr @\exposid{iterator}@ operator+(difference_type n, const @\exposid{iterator}@& i) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + friend constexpr @\exposid{iterator}@ operator-(const @\exposid{iterator}@& i, difference_type n) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + friend constexpr difference_type operator-(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{sized_sentinel_for}@<@\exposid{inner-iterator}@, @\exposid{inner-iterator}@>; + }; +} +\end{codeblock} + +\pnum +The member \grammarterm{typedef-name} \tcode{\exposid{iterator}::iterator_category} +is defined as follows: +\begin{itemize} +\item +If \tcode{invoke_result_t<\exposid{maybe-const}\&, +\exposid{REPEAT}(range_reference_t<\exposid{Base}>, N)...>} +is\linebreak not an lvalue reference, +\tcode{iterator_category} denotes \tcode{input_iterator_tag}. +\item +Otherwise, let \tcode{C} denote the type +\tcode{iterator_traits>::iterator_category}. +\begin{itemize} +\item +If \tcode{\libconcept{derived_from}} +is \tcode{true}, +\tcode{iterator_category} denotes \tcode{ran\-dom_access_iterator_tag}. +\item +Otherwise, +if \tcode{\libconcept{derived_from}} +is \tcode{true}, +\tcode{iterator_category} denotes \tcode{bidirectional_iterator_tag}. +\item +Otherwise, +if \tcode{\libconcept{derived_from}} +is \tcode{true}, +\tcode{iterator_category} denotes \tcode{forward_iterator_tag}. +\item +Otherwise, \tcode{iterator_category} denotes \tcode{input_iterator_tag}. +\end{itemize} +\end{itemize} + +\begin{itemdecl} +constexpr @\exposid{iterator}@(@\exposid{Parent}@& parent, @\exposid{inner-iterator}@ inner); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \exposid{parent_} with \tcode{addressof(parent)} and +\exposid{inner_} with \tcode{std::move(inner)}. +\end{itemdescr} + +\begin{itemdecl} +constexpr @\exposid{iterator}@(@\exposid{iterator}@ i) + requires Const && @\libconcept{convertible_to}@<@\exposid{inner-iterator}@, @\exposid{inner-iterator}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \exposid{parent_} with \tcode{i.\exposid{parent_}} and +\exposid{inner_} with \tcode{std::move(i.\exposid{inner_})}. +\end{itemdescr} + +\begin{itemdecl} +constexpr decltype(auto) operator*() const noexcept(@\seebelow@); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +return apply([&](const auto&... iters) -> decltype(auto) { + return invoke(*@\exposid{parent_}@->@\exposid{fun_}@, *iters...); +}, @\exposid{inner_}@.@\exposid{current_}@); +\end{codeblock} + +\pnum +\remarks +Let \tcode{Is} be the pack \tcode{0, 1, \ldots, (N-1)}. +The exception specification is equivalent to: +\begin{codeblock} +noexcept(invoke(*@\exposid{parent_}@->@\exposid{fun_}@, *std::get(@\exposid{inner_}@.@\exposid{current_}@)...)) +\end{codeblock} +\end{itemdescr} + +\begin{itemdecl} +constexpr @\exposid{iterator}@& operator++(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +++@\exposid{inner_}@; +return *this; +\end{codeblock} +\end{itemdescr} + +\begin{itemdecl} +constexpr @\exposid{iterator}@ operator++(int); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +auto tmp = *this; +++*this; +return tmp; +\end{codeblock} +\end{itemdescr} + +\begin{itemdecl} +constexpr @\exposid{iterator}@& operator--() requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +--@\exposid{inner_}@; +return *this; +\end{codeblock} +\end{itemdescr} + +\begin{itemdecl} +constexpr @\exposid{iterator}@ operator--(int) requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +auto tmp = *this; +--*this; +return tmp; +\end{codeblock} +\end{itemdescr} + +\begin{itemdecl} +constexpr @\exposid{iterator}@& operator+=(difference_type x) requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +@\exposid{inner_}@ += x; +return *this; +\end{codeblock} +\end{itemdescr} + +\begin{itemdecl} +constexpr @\exposid{iterator}@& operator-=(difference_type x) requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +@\exposid{inner_}@ -= x; +return *this; +\end{codeblock} +\end{itemdescr} + +\begin{itemdecl} +constexpr decltype(auto) operator[](difference_type n) const + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +return apply([&](const auto&... iters) -> decltype(auto) { + return invoke(*@\exposid{parent_}@->@\exposid{fun_}@, iters[n]...); +}, @\exposid{inner_}@.@\exposid{current_}@); +\end{codeblock} +\end{itemdescr} + +\begin{itemdecl} +friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y); +friend constexpr bool operator<(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +friend constexpr bool operator>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +friend constexpr bool operator<=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +friend constexpr bool operator>=(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +friend constexpr auto operator<=>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@> && @\libconcept{three_way_comparable}@<@\exposid{inner-iterator}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \placeholder{op} be the operator. + +\pnum +\effects +Equivalent to: \tcode{return x.\exposid{inner_} \placeholder{op} y.\exposid{inner_};} +\end{itemdescr} + +\begin{itemdecl} +friend constexpr @\exposid{iterator}@ operator+(const @\exposid{iterator}@& i, difference_type n) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +friend constexpr @\exposid{iterator}@ operator+(difference_type n, const @\exposid{iterator}@& i) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return \exposid{iterator}(*i.\exposid{parent_}, i.\exposid{inner_} + n);} +\end{itemdescr} + +\begin{itemdecl} +friend constexpr @\exposid{iterator}@ operator-(const @\exposid{iterator}@& i, difference_type n) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return \exposid{iterator}(*i.\exposid{parent_}, i.\exposid{inner_} - n);} +\end{itemdescr} + +\begin{itemdecl} +friend constexpr difference_type operator-(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) + requires @\libconcept{sized_sentinel_for}@<@\exposid{inner-iterator}@, @\exposid{inner-iterator}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return x.\exposid{inner_} - y.\exposid{inner_};} +\end{itemdescr} + +\rSec3[range.adjacent.transform.sentinel]{Class template \tcode{adjacent_transform_view::\exposid{sentinel}}} + +\indexlibraryglobal{adjacent_transform_view::sentinel}% +\begin{codeblock} +namespace std::ranges { + template<@\libconcept{forward_range}@ V, @\libconcept{copy_constructible}@ F, size_t N> + requires @\libconcept{view}@ && (N > 0) && is_object_v && + @\libconcept{regular_invocable}@, N)...> && + @\exposconcept{can-reference}@, N)...>> + template + class adjacent_transform_view::@\exposid{sentinel}@ { + @\exposid{inner-sentinel}@ @\exposid{inner_}@; // \expos + constexpr explicit @\exposid{sentinel}@(@\exposid{inner-sentinel}@ inner); // \expos + + public: + @\exposid{sentinel}@() = default; + constexpr @\exposid{sentinel}@(@\exposid{sentinel}@ i) + requires Const && @\libconcept{convertible_to}@<@\exposid{inner-sentinel}@, @\exposid{inner-sentinel}@>; + + template + requires @\libconcept{sentinel_for}@<@\exposid{inner-sentinel}@, @\exposid{inner-iterator}@> + friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); + + template + requires @\libconcept{sized_sentinel_for}@<@\exposid{inner-sentinel}@, @\exposid{inner-iterator}@> + friend constexpr range_difference_t<@\exposid{maybe-const}@> + operator-(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); + + template + requires @\libconcept{sized_sentinel_for}@<@\exposid{inner-sentinel}@, @\exposid{inner-iterator}@> + friend constexpr range_difference_t<@\exposid{maybe-const}@> + operator-(const @\exposid{sentinel}@& x, const @\exposid{iterator}@& y); + }; +} +\end{codeblock} + +\begin{itemdecl} +constexpr explicit @\exposid{sentinel}@(@\exposid{inner-sentinel}@ inner); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \exposid{inner_} with \tcode{inner}. +\end{itemdescr} + +\begin{itemdecl} +constexpr @\exposid{sentinel}@(@\exposid{sentinel}@ i) + requires Const && @\libconcept{convertible_to}@<@\exposid{inner-sentinel}@, @\exposid{inner-sentinel}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \exposid{inner_} with \tcode{std::move(i.\exposid{inner_})}. +\end{itemdescr} + +\begin{itemdecl} +template + requires @\libconcept{sentinel_for}@<@\exposid{inner-sentinel}@, @\exposid{inner-iterator}@> +friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to \tcode{return x.\exposid{inner_} == y.\exposid{inner_};} +\end{itemdescr} + +\begin{itemdecl} +template + requires @\libconcept{sized_sentinel_for}@<@\exposid{inner-sentinel}@, @\exposid{inner-iterator}@> +friend constexpr range_difference_t<@\exposid{maybe-const}@> + operator-(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); + +template + requires @\libconcept{sized_sentinel_for}@<@\exposid{inner-sentinel}@, @\exposid{inner-iterator}@> +friend constexpr range_difference_t<@\exposid{maybe-const}@> + operator-(const @\exposid{sentinel}@& x, const @\exposid{iterator}@& y); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to \tcode{return x.\exposid{inner_} - y.\exposid{inner_};} +\end{itemdescr} diff --git a/source/support.tex b/source/support.tex index 5088babcb4..f03917530e 100644 --- a/source/support.tex +++ b/source/support.tex @@ -668,6 +668,7 @@ #define @\defnlibxname{cpp_lib_ranges}@ 202110L // also in \libheader{algorithm}, \libheader{functional}, \libheader{iterator}, \libheader{memory}, \libheader{ranges} #define @\defnlibxname{cpp_lib_ranges_starts_ends_with}@ 202106L // also in \libheader{algorithm} +#define @\defnlibxname{cpp_lib_ranges_zip}@ 202110L // also in \libheader{ranges}, \libheader{tuple}, \libheader{utility} #define @\defnlibxname{cpp_lib_raw_memory_algorithms}@ 201606L // also in \libheader{memory} #define @\defnlibxname{cpp_lib_remove_cvref}@ 201711L // also in \libheader{type_traits} #define @\defnlibxname{cpp_lib_result_of_sfinae}@ 201210L // also in \libheader{functional}, \libheader{type_traits} diff --git a/source/utilities.tex b/source/utilities.tex index 3d710a1388..994503e464 100644 --- a/source/utilities.tex +++ b/source/utilities.tex @@ -119,6 +119,21 @@ template struct pair; + template class TQual, template class UQual> + requires requires { typename pair, UQual>, + common_reference_t, UQual>>; } + struct basic_common_reference, pair, TQual, UQual> { + using type = pair, UQual>, + common_reference_t, UQual>>; + }; + + template + requires requires { typename pair, common_type_t>; } + struct common_type, pair> { + using type = pair, common_type_t>; + }; + // \ref{pairs.spec}, pair specialized algorithms template constexpr bool operator==(const pair&, const pair&); @@ -129,6 +144,9 @@ template constexpr void swap(pair& x, pair& y) noexcept(noexcept(x.swap(y))); + template + constexpr void swap(const pair& x, const pair& y) + noexcept(noexcept(x.swap(y))); template constexpr @\seebelow@ make_pair(T1&&, T2&&); @@ -674,22 +692,33 @@ constexpr explicit(@\seebelow@) pair(const T1& x, const T2& y); template constexpr explicit(@\seebelow@) pair(U1&& x, U2&& y); + template + constexpr explicit(@\seebelow@) pair(pair& p); template constexpr explicit(@\seebelow@) pair(const pair& p); template constexpr explicit(@\seebelow@) pair(pair&& p); + template + constexpr explicit(@\seebelow@) pair(const pair&& p); template constexpr pair(piecewise_construct_t, tuple first_args, tuple second_args); constexpr pair& operator=(const pair& p); + constexpr const pair& operator=(const pair& p) const; template constexpr pair& operator=(const pair& p); + template + constexpr const pair& operator=(const pair& p) const; constexpr pair& operator=(pair&& p) noexcept(@\seebelow@); + constexpr const pair& operator=(pair&& p) const; template constexpr pair& operator=(pair&& p); + template + constexpr const pair& operator=(pair&& p) const; constexpr void swap(pair& p) noexcept(@\seebelow@); + constexpr void swap(const pair& p) const noexcept(@\seebelow@); }; template @@ -804,54 +833,38 @@ \indexlibraryctor{pair}% \begin{itemdecl} +template constexpr explicit(@\seebelow@) pair(pair& p); template constexpr explicit(@\seebelow@) pair(const pair& p); +template constexpr explicit(@\seebelow@) pair(pair&& p); +template constexpr explicit(@\seebelow@) pair(const pair&& p); \end{itemdecl} \begin{itemdescr} \pnum -\constraints -\begin{itemize} -\item \tcode{is_constructible_v} is \tcode{true} and -\item \tcode{is_constructible_v} is \tcode{true}. -\end{itemize} - -\pnum -\effects -Initializes members from the corresponding members of the argument. +Let \tcode{\exposid{FWD}(u)} be \tcode{static_cast(u)}. -\pnum -\remarks -The expression inside \keyword{explicit} is equivalent to: -\begin{codeblock} -!is_convertible_v || !is_convertible_v -\end{codeblock} -\end{itemdescr} - -\indexlibraryctor{pair}% -\begin{itemdecl} -template constexpr explicit(@\seebelow@) pair(pair&& p); -\end{itemdecl} - -\begin{itemdescr} \pnum \constraints \begin{itemize} -\item \tcode{is_constructible_v} is \tcode{true} and -\item \tcode{is_constructible_v} is \tcode{true}. +\item +\tcode{is_constructible_v(\exposid{FWD}(p)))>} +is \tcode{true} and +\item +\tcode{is_constructible_v(\exposid{FWD}(p)))>} +is \tcode{true}. \end{itemize} \pnum \effects -Initializes \tcode{first} with -\tcode{std::forward(p.first)} -and \tcode{second} with -\tcode{std::forward(\brk{}p.second)}. +Initializes \tcode{first} with \tcode{get<0>(\exposid{FWD}(p))} and +\tcode{second} with \tcode{get<1>(\exposid{FWD}(p))}. \pnum \remarks The expression inside \keyword{explicit} is equivalent to: \begin{codeblock} -!is_convertible_v || !is_convertible_v +!is_convertible_v(@\exposid{FWD}@(p))), first_type> || +!is_convertible_v(@\exposid{FWD}@(p))), second_type> \end{codeblock} \end{itemdescr} @@ -903,6 +916,30 @@ \tcode{is_copy_assignable_v} is \tcode{true}. \end{itemdescr} +\indexlibrarymember{operator=}{pair}% +\begin{itemdecl} +constexpr const pair& operator=(const pair& p) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\begin{itemize} +\item +\tcode{is_copy_assignable} is \tcode{true} and +\item +\tcode{is_copy_assignable} is \tcode{true}. +\end{itemize} + +\pnum +\effects +Assigns \tcode{p.first} to \tcode{first} and \tcode{p.second} to \tcode{second}. + +\pnum +\returns +\tcode{*this}. +\end{itemdescr} + \indexlibrarymember{operator=}{pair}% \begin{itemdecl} template constexpr pair& operator=(const pair& p); @@ -925,6 +962,30 @@ \tcode{*this}. \end{itemdescr} +\indexlibrarymember{operator=}{pair}% +\begin{itemdecl} +template constexpr const pair& operator=(const pair& p) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\begin{itemize} +\item +\tcode{is_assignable_v} is \tcode{true}, and +\item +\tcode{is_assignable_v} is \tcode{true}. +\end{itemize} + +\pnum +\effects +Assigns \tcode{p.first} to \tcode{first} and \tcode{p.second} to \tcode{second}. + +\pnum +\returns +\tcode{*this}. +\end{itemdescr} + \indexlibrarymember{operator=}{pair}% \begin{itemdecl} constexpr pair& operator=(pair&& p) noexcept(@\seebelow@); @@ -955,6 +1016,31 @@ \end{codeblock} \end{itemdescr} +\indexlibrarymember{operator=}{pair}% +\begin{itemdecl} +constexpr const pair& operator=(pair&& p) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\begin{itemize} +\item +\tcode{is_assignable} is \tcode{true} and +\item +\tcode{is_assignable} is \tcode{true}. +\end{itemize} + +\pnum +\effects +Assigns \tcode{std::forward(p.first)} to \tcode{first} and +\tcode{std::forward(\brk{}p.second)} to \tcode{second}. + +\pnum +\returns +\tcode{*this}. +\end{itemdescr} + \indexlibrarymember{operator=}{pair}% \begin{itemdecl} template constexpr pair& operator=(pair&& p); @@ -978,12 +1064,50 @@ \tcode{*this}. \end{itemdescr} +\indexlibrarymember{operator=}{pair}% +\begin{itemdecl} +template constexpr const pair& operator=(pair&& p) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\begin{itemize} +\item +\tcode{is_assignable_v} is \tcode{true}, and +\item +\tcode{is_assignable_v} is \tcode{true}. +\end{itemize} + +\effects +Assigns \tcode{std::forward(p.first)} to \tcode{first} and +\tcode{std::forward(u.second)} to \tcode{second}. + +\pnum +\returns +\tcode{*this}. +\end{itemdescr} + \indexlibrarymember{swap}{pair}% \begin{itemdecl} constexpr void swap(pair& p) noexcept(@\seebelow@); +constexpr void swap(const pair& p) const noexcept(@\seebelow@); \end{itemdecl} \begin{itemdescr} +\pnum +\mandates +\begin{itemize} +\item +For the first overload, +\tcode{is_swappable_v} is \tcode{true} and +\tcode{is_swappable_v} is \tcode{true}. +\item +For the second overload, +\tcode{is_swappable_v} is \tcode{true} and +\tcode{is_swappable_v} is \tcode{true}. +\end{itemize} + \pnum \expects \tcode{first} is swappable with\iref{swappable.requirements} \tcode{p.first} and @@ -998,9 +1122,14 @@ \pnum \remarks The exception specification is equivalent to: -\begin{codeblock} -is_nothrow_swappable_v && is_nothrow_swappable_v -\end{codeblock} +\begin{itemize} +\item +\tcode{is_nothrow_swappable_v \&\& is_nothrow_swappable_v} +for the\newline first overload, and +\item +\tcode{is_nothrow_swappable_v \&\& is_nothrow_swappable_v} +for the second overload. +\end{itemize} \end{itemdescr} \rSec2[pairs.spec]{Specialized algorithms} @@ -1039,13 +1168,23 @@ \begin{itemdecl} template constexpr void swap(pair& x, pair& y) noexcept(noexcept(x.swap(y))); +template + constexpr void swap(const pair& x, const pair& y) noexcept(noexcept(x.swap(y))); \end{itemdecl} \begin{itemdescr} \pnum \constraints +\begin{itemize} +\item +For the first overload, \tcode{is_swappable_v} is \tcode{true} and \tcode{is_swappable_v} is \tcode{true}. +\item +For the second overload, +\tcode{is_swappable_v} is \tcode{true} and +\tcode{is_swappable_v} is \tcode{true}. +\end{itemize} \pnum \effects @@ -1219,6 +1358,19 @@ template class tuple; + template class TQual, + template class UQual> + requires requires { typename tuple, UQual>...>; } + struct basic_common_reference, tuple, TQual, UQual> { + using type = tuple, UQual>...>; + }; + + template + requires requires { typename tuple...>; } + struct common_type, tuple> { + using type = tuple...>; + }; + // \ref{tuple.creation}, tuple creation functions inline constexpr @\unspec@ ignore; @@ -1288,6 +1440,8 @@ // \ref{tuple.special}, specialized algorithms template constexpr void swap(tuple& x, tuple& y) noexcept(@\seebelow@); + template + constexpr void swap(const tuple& x, const tuple& y) noexcept(@\seebelow@); // \ref{tuple.helper}, tuple helper classes template @@ -1312,15 +1466,23 @@ tuple(const tuple&) = default; tuple(tuple&&) = default; + template + constexpr explicit(@\seebelow@) tuple(tuple&); template constexpr explicit(@\seebelow@) tuple(const tuple&); template constexpr explicit(@\seebelow@) tuple(tuple&&); + template + constexpr explicit(@\seebelow@) tuple(const tuple&&); + template + constexpr explicit(@\seebelow@) tuple(pair&); // only if \tcode{sizeof...(Types) == 2} template constexpr explicit(@\seebelow@) tuple(const pair&); // only if \tcode{sizeof...(Types) == 2} template constexpr explicit(@\seebelow@) tuple(pair&&); // only if \tcode{sizeof...(Types) == 2} + template + constexpr explicit(@\seebelow@) tuple(const pair&&); // only if \tcode{sizeof...(Types) == 2} // allocator-extended constructors template @@ -1336,35 +1498,59 @@ constexpr tuple(allocator_arg_t, const Alloc& a, const tuple&); template constexpr tuple(allocator_arg_t, const Alloc& a, tuple&&); + template + constexpr explicit(@\seebelow@) + tuple(allocator_arg_t, const Alloc& a, tuple&); template constexpr explicit(@\seebelow@) tuple(allocator_arg_t, const Alloc& a, const tuple&); template constexpr explicit(@\seebelow@) tuple(allocator_arg_t, const Alloc& a, tuple&&); + template + constexpr explicit(@\seebelow@) + tuple(allocator_arg_t, const Alloc& a, const tuple&&); + template + constexpr explicit(@\seebelow@) + tuple(allocator_arg_t, const Alloc& a, pair&); template constexpr explicit(@\seebelow@) tuple(allocator_arg_t, const Alloc& a, const pair&); template constexpr explicit(@\seebelow@) tuple(allocator_arg_t, const Alloc& a, pair&&); + template + constexpr explicit(@\seebelow@) + tuple(allocator_arg_t, const Alloc& a, const pair&&); // \ref{tuple.assign}, \tcode{tuple} assignment constexpr tuple& operator=(const tuple&); + constexpr const tuple& operator=(const tuple&) const; constexpr tuple& operator=(tuple&&) noexcept(@\seebelow@); + constexpr const tuple& operator=(tuple&&) const; template constexpr tuple& operator=(const tuple&); + template + constexpr const tuple& operator=(const tuple&) const; template constexpr tuple& operator=(tuple&&); + template + constexpr const tuple& operator=(tuple&&) const; template constexpr tuple& operator=(const pair&); // only if \tcode{sizeof...(Types) == 2} + template + constexpr const tuple& operator=(const pair&) const; + // only if \tcode{sizeof...(Types) == 2} template constexpr tuple& operator=(pair&&); // only if \tcode{sizeof...(Types) == 2} + template + constexpr const tuple& operator=(pair&&) const; // only if \tcode{sizeof...(Types) == 2} // \ref{tuple.swap}, \tcode{tuple} swap constexpr void swap(tuple&) noexcept(@\seebelow@); + constexpr void swap(const tuple&) const noexcept(@\seebelow@); }; template @@ -1538,130 +1724,81 @@ \indexlibraryctor{tuple}% \begin{itemdecl} +template constexpr explicit(@\seebelow@) tuple(tuple& u); template constexpr explicit(@\seebelow@) tuple(const tuple& u); +template constexpr explicit(@\seebelow@) tuple(tuple&& u); +template constexpr explicit(@\seebelow@) tuple(const tuple&& u); \end{itemdecl} \begin{itemdescr} \pnum -\constraints -\begin{itemize} -\item -\tcode{sizeof...(Types)} equals \tcode{sizeof...(UTypes)} and - -\item -\tcode{is_constructible_v<$\tcode{T}_i$, const $\tcode{U}_i$\&>} is \tcode{true} for all $i$, and - -\item -either -\tcode{sizeof...(Types)} is not 1, or -(when \tcode{Types...} expands to \tcode{T} and \tcode{UTypes...} expands to \tcode{U}) -\tcode{is_convertible_v\&, T>}, \tcode{is_constructible_v\&>}, and \tcode{is_same_v} are all \tcode{false}. -\end{itemize} +Let \tcode{I} be the pack \tcode{0, 1, ..., (sizeof...(Types) - 1)}.\newline +Let \tcode{\exposid{FWD}(u)} be \tcode{static_cast(u)}. -\pnum -\effects -Initializes each element of \tcode{*this} -with the corresponding element of \tcode{u}. - -\pnum -\remarks -The expression inside \keyword{explicit} is equivalent to: -\begin{codeblock} -!conjunction_v...> -\end{codeblock} -\end{itemdescr} - -\indexlibraryctor{tuple}% -\begin{itemdecl} -template constexpr explicit(@\seebelow@) tuple(tuple&& u); -\end{itemdecl} - -\begin{itemdescr} \pnum \constraints \begin{itemize} \item \tcode{sizeof...(Types)} equals \tcode{sizeof...(UTypes)}, and - \item -\tcode{is_constructible_v<$\tcode{T}_i$, $\tcode{U}_i$>} is \tcode{true} for all $i$, and - +\tcode{(is_constructible_v(\exposid{FWD}(u)))> \&\& ...)} +is \tcode{true}, and \item -either -\tcode{sizeof...(Types)} is not 1, or -(when \tcode{Types...} expands to \tcode{T} and \tcode{UTypes...} expands to \tcode{U}) -\tcode{is_convertible_v, T>}, \tcode{is_constructible_v>}, -and \tcode{is_same_v} are all \tcode{false}. +either \tcode{sizeof...(Types)} is not 1, or +(when \tcode{Types...} expands to \tcode{T} and +\tcode{UTypes...} expands to \tcode{U}) +\tcode{is_convertible_v}, +\tcode{is_constructible_v}, and +\tcode{is_same_v} are all \tcode{false}. \end{itemize} \pnum \effects -For all $i$, -initializes the $i^\text{th}$ element of \tcode{*this} with -\tcode{std::forward<$\tcode{U}_i$>(get<$i$>(u))}. +For all $i$, initializes the $i^\textrm{th}$ element of \tcode{*this} +with \tcode{get<$i$>(\exposid{FWD}(u))}. \pnum \remarks The expression inside \keyword{explicit} is equivalent to: \begin{codeblock} -!conjunction_v...> +!(is_convertible_v(@\exposid{FWD}@(u))), Types> && ...) \end{codeblock} \end{itemdescr} \indexlibraryctor{tuple}% -\indexlibraryglobal{pair}% \begin{itemdecl} +template constexpr explicit(@\seebelow@) tuple(pair& u); template constexpr explicit(@\seebelow@) tuple(const pair& u); +template constexpr explicit(@\seebelow@) tuple(pair&& u); +template constexpr explicit(@\seebelow@) tuple(const pair&& u); \end{itemdecl} \begin{itemdescr} \pnum -\constraints -\begin{itemize} -\item \tcode{sizeof...(Types)} is 2, -\item \tcode{is_constructible_v<$\tcode{T}_0$, const U1\&>} is \tcode{true}, and -\item \tcode{is_constructible_v<$\tcode{T}_1$, const U2\&>} is \tcode{true}. -\end{itemize} - -\pnum -\effects -Initializes the first element with \tcode{u.first} and the -second element with \tcode{u.second}. +Let \tcode{\exposid{FWD}(u)} be \tcode{static_cast(u)}. -\pnum -\remarks -The expression inside \keyword{explicit} is equivalent to: -\begin{codeblock} -!is_convertible_v || !is_convertible_v -\end{codeblock} -\end{itemdescr} - -\indexlibraryctor{tuple}% -\indexlibraryglobal{pair}% -\begin{itemdecl} -template constexpr explicit(@\seebelow@) tuple(pair&& u); -\end{itemdecl} - -\begin{itemdescr} \pnum \constraints \begin{itemize} -\item \tcode{sizeof...(Types)} is 2, -\item \tcode{is_constructible_v<$\tcode{T}_0$, U1>} is \tcode{true}, and -\item \tcode{is_constructible_v<$\tcode{T}_1$, U2>} is \tcode{true}. +\item +\tcode{sizeof...(Types)} is 2, +\item +\tcode{is_constructible_v<$\tcode{T}_0$, decltype(get<0>(\exposid{FWD}(u)))>} is \tcode{true}, and +\item +\tcode{is_constructible_v<$\tcode{T}_1$, decltype(get<1>(\exposid{FWD}(u)))>} is \tcode{true}. \end{itemize} \pnum \effects -Initializes the first element with -\tcode{std::forward(u.first)} and the -second element with \tcode{std::forward(u.second)}. +Initializes the first element with \tcode{get<0>(\exposid{FWD}(u))} and +the second element with \tcode{get<1>(\exposid{FWD}(\brk{}u))}. \pnum \remarks -The expression inside \keyword{explicit} is equivalent to: +The expression inside \tcode{explicit} is equivalent to: \begin{codeblock} -!is_convertible_v || !is_convertible_v +!is_convertible_v(@\exposid{FWD}@(u))), @$\tcode{T}_0$@> || +!is_convertible_v(@\exposid{FWD}@(u))), @$\tcode{T}_1$@> \end{codeblock} \end{itemdescr} @@ -1680,18 +1817,30 @@ constexpr tuple(allocator_arg_t, const Alloc& a, const tuple&); template constexpr tuple(allocator_arg_t, const Alloc& a, tuple&&); +template + constexpr explicit(@\seebelow@) + tuple(allocator_arg_t, const Alloc& a, tuple&); template constexpr explicit(@\seebelow@) tuple(allocator_arg_t, const Alloc& a, const tuple&); template constexpr explicit(@\seebelow@) tuple(allocator_arg_t, const Alloc& a, tuple&&); +template + constexpr explicit(@\seebelow@) + tuple(allocator_arg_t, const Alloc& a, const tuple&&); +template + constexpr explicit(@\seebelow@) + tuple(allocator_arg_t, const Alloc& a, pair&); template constexpr explicit(@\seebelow@) tuple(allocator_arg_t, const Alloc& a, const pair&); template constexpr explicit(@\seebelow@) tuple(allocator_arg_t, const Alloc& a, pair&&); +template + constexpr explicit(@\seebelow@) + tuple(allocator_arg_t, const Alloc& a, const pair&&); \end{itemdecl} \begin{itemdescr} @@ -1737,6 +1886,25 @@ \tcode{is_copy_assignable_v<$\tcode{T}_i$>} is \tcode{true} for all $i$. \end{itemdescr} +\indexlibrarymember{operator=}{tuple}% +\begin{itemdecl} +constexpr const tuple& operator=(const tuple& u) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{(is_copy_assignable_v \&\& ...)} is \tcode{true}. + +\pnum +\effects +Assigns each element of \tcode{u} to the corresponding element of \tcode{*this}. + +\pnum +\returns +\tcode{*this}. +\end{itemdescr} + \indexlibrarymember{operator=}{tuple}% \begin{itemdecl} constexpr tuple& operator=(tuple&& u) noexcept(@\seebelow@); @@ -1767,6 +1935,26 @@ where $\mathtt{T}_i$ is the $i^\text{th}$ type in \tcode{Types}. \end{itemdescr} +\indexlibrarymember{operator=}{tuple}% +\begin{itemdecl} +constexpr const tuple& operator=(tuple&& u) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\tcode{(is_assignable_v \&\& ...)} is \tcode{true}. + +\pnum +\effects +For all $i$, +assigns \tcode{std::forward(get<$i$>(u))} to \tcode{get<$i$>(*this)}. + +\pnum +\returns +\tcode{*this}. +\end{itemdescr} + \indexlibrarymember{operator=}{tuple}% \begin{itemdecl} template constexpr tuple& operator=(const tuple& u); @@ -1790,6 +1978,30 @@ \tcode{*this}. \end{itemdescr} +\indexlibrarymember{operator=}{tuple}% +\begin{itemdecl} +template constexpr const tuple& operator=(const tuple& u) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\begin{itemize} +\item +\tcode{sizeof...(Types)} equals \tcode{sizeof...(UTypes)} and +\item +\tcode{(is_assignable_v \&\& ...)} is \tcode{true}. +\end{itemize} + +\pnum +\effects +Assigns each element of \tcode{u} to the corresponding element of \tcode{*this}. + +\pnum +\returns +\tcode{*this}. +\end{itemdescr} + \indexlibrarymember{operator=}{tuple}% \begin{itemdecl} template constexpr tuple& operator=(tuple&& u); @@ -1813,6 +2025,31 @@ \tcode{*this}. \end{itemdescr} +\indexlibrarymember{operator=}{tuple}% +\begin{itemdecl} +template constexpr const tuple& operator=(tuple&& u) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\begin{itemize} +\item +\tcode{sizeof...(Types)} equals \tcode{sizeof...(UTypes)} and +\item +\tcode{(is_assignable_v \&\& ...)} is \tcode{true}. +\end{itemize} + +\pnum +\effects +For all $i$, +assigns \tcode{std::forward(get<$i$>(u))} to \tcode{get<$i$>(*this)}. + +\pnum +\returns +\tcode{*this}. +\end{itemdescr} + \indexlibrarymember{operator=}{tuple}% \indexlibraryglobal{pair}% \begin{itemdecl} @@ -1838,6 +2075,33 @@ \tcode{*this}. \end{itemdescr} +\indexlibrarymember{operator=}{tuple}% +\begin{itemdecl} +template constexpr const tuple& operator=(const pair& u) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\begin{itemize} +\item +\tcode{sizeof...(Types)} is 2, +\item +\tcode{is_assignable_v} is \tcode{true}, and +\item +\tcode{is_assignable_v} is \tcode{true}. +\end{itemize} + +\pnum +\effects +Assigns \tcode{u.first} to the first element and +\tcode{u.second} to the second element. + +\pnum +\returns +\tcode{*this}. +\end{itemdescr} + \indexlibrarymember{operator=}{tuple}% \indexlibraryglobal{pair}% \begin{itemdecl} @@ -1864,14 +2128,53 @@ \tcode{*this}. \end{itemdescr} +\indexlibrarymember{operator=}{tuple}% +\begin{itemdecl} +template constexpr const tuple& operator=(pair&& u) const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\constraints +\begin{itemize} +\item +\tcode{sizeof...(Types)} is 2, +\item +\tcode{is_assignable_v} is \tcode{true}, and +\item +\tcode{is_assignable_v} is \tcode{true}. +\end{itemize} + +\pnum +\effects +Assigns \tcode{std::forward(u.first)} to the first element and\\ +\tcode{std::forward(u.second)} to the second element. + +\pnum +\returns +\tcode{*this}. +\end{itemdescr} + \rSec3[tuple.swap]{\tcode{swap}} \indexlibrarymember{swap}{tuple}% \begin{itemdecl} constexpr void swap(tuple& rhs) noexcept(@\seebelow@); +constexpr void swap(const tuple& rhs) const noexcept(@\seebelow@); \end{itemdecl} \begin{itemdescr} +\pnum +\mandates +\begin{itemize} +\item +For the first overload, +\tcode{(is_swappable_v \&\& ...)} is \tcode{true}. +\item +For the second overload, +\tcode{(is_swappable_v \&\& ...)} is \tcode{true}. +\end{itemize} + \pnum \expects Each element in \tcode{*this} is swappable with\iref{swappable.requirements} @@ -1888,13 +2191,13 @@ \pnum \remarks -The exception specification is equivalent to the logical -\logop{AND} of the following expressions: - -\begin{codeblock} -is_nothrow_swappable_v<@$\mathtt{T}_i$@> -\end{codeblock} -where $\mathtt{T}_i$ is the $i^\text{th}$ type in \tcode{Types}. +The exception specification is equivalent to +\begin{itemize} +\item +\tcode{(is_nothrow_swappable_v \&\& ...)} for the first overload and +\item +\tcode{(is_nothrow_swappable_v \&\& ...)} for the second overload. +\end{itemize} \end{itemdescr} \rSec2[tuple.creation]{Tuple creation functions} @@ -2367,13 +2670,21 @@ \begin{itemdecl} template constexpr void swap(tuple& x, tuple& y) noexcept(@\seebelow@); +template + constexpr void swap(const tuple& x, const tuple& y) noexcept(@\seebelow@); \end{itemdecl} \begin{itemdescr} \pnum \constraints -\tcode{is_swappable_v} is \tcode{true} -for every type \tcode{T} in \tcode{Types}. +\begin{itemize} +\item +For the first overload, +\tcode{(is_swappable_v \&\& ...)} is \tcode{true}. +\item +For the second overload, +\tcode{(is_swappable_v \&\& ...)} is \tcode{true}. +\end{itemize} \pnum \effects @@ -7087,12 +7398,18 @@ template constexpr auto uses_allocator_construction_args(const Alloc& alloc, U&& u, V&& v) noexcept; + template + constexpr auto uses_allocator_construction_args(const Alloc& alloc, + pair& pr) noexcept; template constexpr auto uses_allocator_construction_args(const Alloc& alloc, const pair& pr) noexcept; template constexpr auto uses_allocator_construction_args(const Alloc& alloc, pair&& pr) noexcept; + template + constexpr auto uses_allocator_construction_args(const Alloc& alloc, + const pair&& pr) noexcept; template constexpr T make_obj_using_allocator(const Alloc& alloc, Args&&... args); template @@ -7983,6 +8300,9 @@ \indexlibraryglobal{uses_allocator_construction_args}% \begin{itemdecl} +template + constexpr auto uses_allocator_construction_args(const Alloc& alloc, + pair& pr) noexcept; template constexpr auto uses_allocator_construction_args(const Alloc& alloc, const pair& pr) noexcept; @@ -8008,6 +8328,9 @@ template constexpr auto uses_allocator_construction_args(const Alloc& alloc, pair&& pr) noexcept; +template + constexpr auto uses_allocator_construction_args(const Alloc& alloc, + const pair&& pr) noexcept; \end{itemdecl} \begin{itemdescr}