Skip to content

Commit e85af95

Browse files
committed
P0896R4 The One Ranges Proposal
1 parent 485a623 commit e85af95

13 files changed

+14452
-2254
lines changed

source/algorithms.tex

Lines changed: 3537 additions & 610 deletions
Large diffs are not rendered by default.

source/compatibility.tex

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2077,6 +2077,19 @@
20772077
Translation units compiled against this version of \Cpp{} may be incompatible with
20782078
translation units compiled against \CppXVII{}, either failing to link or having undefined behavior.
20792079

2080+
\rSec2[diff.cpp17.alg.reqs]{\ref{algorithms}: algorithms library}
2081+
2082+
\diffref{algorithms.requirements}
2083+
\change
2084+
The number and order of deducible template parameters for algorithm declarations
2085+
is now unspecified, instead of being as-declared.
2086+
\rationale Increase implementor freedom and allow some function templates
2087+
to be implemented as function objects with templated call operators.
2088+
\effect
2089+
A valid \CppXVII{} program that passes explicit template arguments to
2090+
algorithms not explicitly specified to allow such in this version of \Cpp{}
2091+
may fail to compile or have undefined behavior.
2092+
20802093
\rSec2[diff.cpp17.input.output]{\ref{input.output}: input/output library}
20812094

20822095
\diffref{istream.extractors}

source/concepts.tex

Lines changed: 117 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,11 @@
178178
concept Assignable = @\seebelow@;
179179

180180
// \ref{concept.swappable}, concept \libconcept{Swappable}
181+
namespace ranges {
182+
inline namespace @\unspec@ {
183+
inline constexpr @\unspec@ swap = @\unspec@;
184+
}
185+
}
181186
template<class T>
182187
concept Swappable = @\seebelow@;
183188
template<class T, class U>
@@ -531,78 +536,125 @@
531536

532537
\rSec2[concept.swappable]{Concept \libconcept{Swappable}}
533538

534-
\indexlibrary{\idxcode{Swappable}}%
535-
\begin{itemdecl}
536-
template<class T>
537-
concept Swappable = is_swappable_v<T>;
538-
\end{itemdecl}
539-
540-
\begin{itemdescr}
541539
\pnum
542-
Let \tcode{a1} and \tcode{a2} denote distinct equal objects of type \tcode{T},
543-
and let \tcode{b1} and \tcode{b2} similarly denote distinct equal objects of
544-
type \tcode{T}. \tcode{\libconcept{Swappable}<T>} is satisfied only if after
545-
evaluating either \tcode{swap(a1, b1)} or \tcode{swap(b1, a1)} in the context
546-
described below, \tcode{a1} is equal to \tcode{b2} and \tcode{b1} is equal to
547-
\tcode{a2}.
540+
Let \tcode{t1} and \tcode{t2} be equality-preserving expressions that denote
541+
distinct equal objects of type \tcode{T}, and let \tcode{u1} and \tcode{u2}
542+
similarly denote distinct equal objects of type \tcode{U}.
543+
\begin{note}
544+
\tcode{t1} and \tcode{u1} can denote distinct objects, or the same object.
545+
\end{note}
546+
An operation
547+
\term{exchanges the values} denoted by \tcode{t1} and \tcode{u1} if and only
548+
if the operation modifies neither \tcode{t2} nor \tcode{u2} and:
549+
\begin{itemize}
550+
\item If \tcode{T} and \tcode{U} are the same type, the result of the operation
551+
is that \tcode{t1} equals \tcode{u2} and \tcode{u1} equals \tcode{t2}.
552+
553+
\item If \tcode{T} and \tcode{U} are different types that model
554+
\libconcept{CommonReference<const T\&, const U\&>},
555+
the result of the operation is that
556+
\tcode{C(t1)} equals \tcode{C(u2)}
557+
and
558+
\tcode{C(u1)} equals \tcode{C(t2)}
559+
where \tcode{C} is \tcode{common_reference_t<const T\&, const U\&>}.
560+
\end{itemize}
548561

549562
\pnum
550-
The context in which \tcode{swap(a1, b1)} or \tcode{swap(b1, a1)} is evaluated
551-
shall ensure that a binary non-member function named \tcode{swap} is selected via
552-
overload resolution\iref{over.match} on a candidate set that includes:
563+
\indexlibrary{\idxcode{ranges::swap}}%
564+
The name \tcode{ranges::swap} denotes a customization point
565+
object\iref{customization.point.object}. The expression
566+
\tcode{ranges::swap(E1, E2)} for some subexpressions \tcode{E1}
567+
and \tcode{E2} is expression-equivalent to an expression
568+
\tcode{S} determined as follows:
569+
553570
\begin{itemize}
554-
\item the two \tcode{swap} function templates defined in
555-
\tcode{<utility>}\iref{utility} and
556-
\item the lookup set produced by argument-dependent
557-
lookup\iref{basic.lookup.argdep}.
571+
\item
572+
\tcode{S} is \tcode{(void)swap(E1, E2)}\footnote{The name \tcode{swap} is used
573+
here unqualified.} if \tcode{E1} or \tcode{E2}
574+
has class or enumeration type\iref{basic.compound} and that expression is valid, with
575+
overload resolution performed in a context that includes the declarations
576+
\begin{codeblock}
577+
template<class T>
578+
void swap(T&, T&) = delete;
579+
template<class T, size_t N>
580+
void swap(T(&)[N], T(&)[N]) = delete;
581+
\end{codeblock}
582+
and does not include a declaration of \tcode{ranges::swap}.
583+
If the function selected by overload resolution does not
584+
exchange the values denoted by
585+
\tcode{E1} and \tcode{E2},
586+
the program is ill-formed with no diagnostic required.
587+
588+
\item
589+
Otherwise, if \tcode{E1} and \tcode{E2}
590+
are lvalues of array types\iref{basic.compound}
591+
with equal extent and \tcode{ranges::swap(*E1, *E2)}
592+
is a valid expression,
593+
\tcode{S} is \tcode{(void)ranges::swap_ranges(E1, E2)},
594+
except that
595+
\tcode{noexcept(S)} is equal to
596+
\tcode{noexcept(\brk{}ranges::swap(*E1, *E2))}.
597+
598+
\item
599+
Otherwise, if \tcode{E1} and \tcode{E2} are lvalues of the
600+
same type \tcode{T} that models \libconcept{MoveConstructible<T>} and
601+
\libconcept{Assignable<T\&, T>},
602+
\tcode{S} is an expression that exchanges the denoted values.
603+
\tcode{S} is a constant expression if
604+
\begin{itemize}
605+
\item \tcode{T} is a literal type\iref{basic.types},
606+
\item both \tcode{E1 = std::move(E2)} and \tcode{E2 = std::move(E1)} are
607+
constant subexpressions\iref{defns.const.subexpr}, and
608+
\item the full-expressions of the initializers in the declarations
609+
\begin{codeblock}
610+
T t1(std::move(E1));
611+
T t2(std::move(E2));
612+
\end{codeblock}
613+
614+
are constant subexpressions.
615+
\end{itemize}
616+
\tcode{noexcept(S)} is equal to
617+
\tcode{is_nothrow_move_constructible_v<T> \&\& is_nothrow_move_assignable\-_v<T>}.
618+
619+
\item
620+
Otherwise, \tcode{ranges::swap(E1, E2)} is ill-formed.
621+
\begin{note}
622+
This case can result in substitution failure when \tcode{ranges::swap(E1, E2)}
623+
appears in the immediate context of a template instantiation.
624+
\end{note}
558625
\end{itemize}
559-
\end{itemdescr}
626+
627+
\pnum
628+
\begin{note}
629+
Whenever \tcode{ranges::swap(E1, E2)} is a valid expression, it
630+
exchanges the values denoted by
631+
\tcode{E1} and \tcode{E2} and has type \tcode{void}.
632+
\end{note}
633+
634+
\indexlibrary{\idxcode{Swappable}}%
635+
\begin{itemdecl}
636+
template<class T>
637+
concept Swappable = requires(T& a, T& b) { ranges::swap(a, b); };
638+
\end{itemdecl}
560639

561640
\indexlibrary{\idxcode{SwappableWith}}%
562641
\begin{itemdecl}
563642
template<class T, class U>
564643
concept SwappableWith =
565-
is_swappable_with_v<T, T> && is_swappable_with_v<U, U> &&
566644
CommonReference<const remove_reference_t<T>&, const remove_reference_t<U>&> &&
567-
is_swappable_with_v<T, U> && is_swappable_with_v<U, T>;
645+
requires(T&& t, U&& u) {
646+
ranges::swap(std::forward<T>(t), std::forward<T>(t));
647+
ranges::swap(std::forward<U>(u), std::forward<U>(u));
648+
ranges::swap(std::forward<T>(t), std::forward<U>(u));
649+
ranges::swap(std::forward<U>(u), std::forward<T>(t));
650+
};
568651
\end{itemdecl}
569652

570-
\begin{itemdescr}
571-
\pnum
572-
Let:
573-
\begin{itemize}
574-
\item \tcode{t1} and \tcode{t2} denote distinct equal objects of type
575-
\tcode{remove_cvref_t<T>},
576-
\item $E_t$ be an expression that denotes \tcode{t1} such that
577-
\tcode{decltype(($E_t$))} is \tcode{T},
578-
\item \tcode{u1} and \tcode{u2} similarly denote distinct equal objects of type
579-
\tcode{remove_cvref_t<U>},
580-
\item $E_u$ be an expression that denotes \tcode{u1} such that
581-
\tcode{decltype(($E_u$))} is \tcode{U}, and
582-
\item \tcode{C} be
583-
% This comfortably fits on one line as a codeblock, but overfills the page as
584-
% tcode. :(
585-
\begin{codeblock}
586-
common_reference_t<const remove_reference_t<T>&, const remove_reference_t<U>&>
587-
\end{codeblock}
588-
\end{itemize}
589-
\tcode{\libconcept{SwappableWith}<T, U>} is satisfied only if after evaluating
590-
either \tcode{swap($E_t$, $E_u$)} or \tcode{swap($E_u$, $E_t$)} in the context
591-
described above, \tcode{C(t1)} is equal to \tcode{C(u2)} and \tcode{C(u1)} is
592-
equal to \tcode{C(t2)}.
593-
594653
\pnum
595-
The context in which \tcode{swap($E_t$, $E_u$)} or \tcode{swap($E_u$, $E_t$)}
596-
is evaluated shall ensure that a binary non-member function named \tcode{swap} is
597-
selected via overload resolution\iref{over.match} on a candidate set that
598-
includes:
599-
\begin{itemize}
600-
\item the two \tcode{swap} function templates defined in
601-
\tcode{<utility>}\iref{utility} and
602-
\item the lookup set produced by argument-dependent
603-
lookup\iref{basic.lookup.argdep}.
604-
\end{itemize}
605-
\end{itemdescr}
654+
\begin{note}
655+
The semantics of the \libconcept{Swappable} and \libconcept{SwappableWith}
656+
concepts are fully defined by the \tcode{ranges::swap} customization point.
657+
\end{note}
606658

607659
\pnum
608660
\begin{example}
@@ -613,29 +665,27 @@
613665
#include <concepts>
614666
#include <utility>
615667

668+
namespace ranges = std::ranges;
669+
616670
template<class T, std::SwappableWith<T> U>
617671
void value_swap(T&& t, U&& u) {
618-
using std::swap;
619-
swap(std::forward<T>(t), std::forward<U>(u)); // OK: uses ``swappable with'' conditions
620-
// for rvalues and lvalues
672+
ranges::swap(std::forward<T>(t), std::forward<U>(u));
621673
}
622674

623675
template<std::Swappable T>
624676
void lv_swap(T& t1, T& t2) {
625-
using std::swap;
626-
swap(t1, t2); // OK: uses swappable conditions for
627-
} // lvalues of type \tcode{T}
677+
ranges::swap(t1, t2);
678+
}
628679

629680
namespace N {
630681
struct A { int m; };
631682
struct Proxy { A* a; };
632683
Proxy proxy(A& a) { return Proxy{ &a }; }
633684

634685
void swap(A& x, Proxy p) {
635-
std::swap(x.m, p.a->m); // OK: uses context equivalent to swappable
636-
// conditions for fundamental types
686+
ranges::swap(x.m, p.a->m);
637687
}
638-
void swap(Proxy p, A& x) { swap(x, p); } // satisfy symmetry constraint
688+
void swap(Proxy p, A& x) { swap(x, p); } // satisfy symmetry requirement
639689
}
640690

641691
int main() {

source/containers.tex

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -454,9 +454,11 @@
454454
\pnum
455455
\indextext{container!contiguous}%
456456
A \defn{contiguous container}
457-
is a container that supports random access iterators\iref{random.access.iterators}
458-
and whose member types \tcode{iterator} and \tcode{const_iterator}
459-
are contiguous iterators\iref{iterator.requirements.general}.
457+
is a container
458+
whose member types \tcode{iterator} and \tcode{const_iterator}
459+
meet the
460+
\oldconcept{RandomAccessIterator} requirements\iref{random.access.iterators} and
461+
model \libconcept{ContiguousIterator}\iref{iterator.concept.contiguous}.
460462

461463
\pnum
462464
\tref{containers.optional.operations} lists operations that are provided
@@ -9828,9 +9830,12 @@
98289830
the storage of which is owned by some other object.
98299831

98309832
\pnum
9831-
The iterator types \tcode{span::iterator} and \tcode{span::const_iterator} are
9832-
random access iterators\iref{random.access.iterators},
9833-
contiguous iterators\iref{iterator.requirements.general}, and
9833+
The iterator types \tcode{span::iterator} and \tcode{span::const_iterator}
9834+
model \libconcept{ContiguousIterator}\iref{iterator.concept.contiguous},
9835+
meet the \oldconcept{RandomAccessIterator}
9836+
requirements\iref{random.access.iterators},
9837+
and
9838+
meet the requirements for
98349839
constexpr iterators\iref{iterator.requirements.general}.
98359840
All requirements on container iterators\iref{container.requirements} apply to
98369841
\tcode{span::iterator} and \tcode{span::const_iterator} as well.
@@ -9912,6 +9917,9 @@
99129917
constexpr const_reverse_iterator crbegin() const noexcept;
99139918
constexpr const_reverse_iterator crend() const noexcept;
99149919

9920+
friend constexpr iterator begin(span s) noexcept { return s.begin(); }
9921+
friend constexpr iterator end(span s) noexcept { return s.end(); }
9922+
99159923
private:
99169924
pointer data_; // \expos
99179925
index_type size_; // \expos

0 commit comments

Comments
 (0)