From 6d4a94f35cb9e567c0c1acab3483dbfeb74693d2 Mon Sep 17 00:00:00 2001 From: Jens Maurer Date: Wed, 9 Feb 2022 17:55:57 +0100 Subject: [PATCH] P1206R7 Conversions from ranges to containers - Fix misnamed constructor in [multiset.cons] - Fix garbled constructor in [stack.defn] - Fix bad pack expansion "std::forward(args)..." --- source/containers.tex | 1127 ++++++++++++++++++++++++++++++++++++++++- source/ranges.tex | 228 +++++++++ source/strings.tex | 90 ++++ source/support.tex | 4 + 4 files changed, 1424 insertions(+), 25 deletions(-) diff --git a/source/containers.tex b/source/containers.tex index 72b49c7066..4641fdbdbf 100644 --- a/source/containers.tex +++ b/source/containers.tex @@ -945,6 +945,14 @@ but specialized allocators can choose a different definition. \end{note} +\pnum +The following exposition-only concept is used in the definition of containers: +\begin{codeblock} +template +concept @\defexposconcept{container-compatible-range}@ = // \expos + ranges::@\libconcept{input_range}@ && @\libconcept{convertible_to}@, T>; +\end{codeblock} + \pnum In this subclause, \begin{itemize} @@ -1270,6 +1278,9 @@ \item \tcode{[i, j)} denotes a valid range, \item +\tcode{rg} denotes a value of a type \tcode{R} +that models \tcode{\exposconcept{container-compatible-range}}, +\item \tcode{il} designates an object of type \tcode{initializer_list}, \item \tcode{n} denotes a value of type \tcode{X::size_type}, @@ -1348,6 +1359,30 @@ \tcode{distance(u.begin(), u.end()) == distance(i, j)} is \tcode{true}. \end{itemdescr} +\begin{itemdecl} +X(from_range, rg) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{T} is \oldconcept{EmplaceConstructible} into \tcode{X} +from \tcode{*ranges::begin(rg)}. +For \tcode{vector}, +if \tcode{R} models +neither \libconcept{sized_range} nor \libconcept{forward_range}, +\tcode{T} is also \oldconcept{MoveInsertable} into \tcode{X}. + +\pnum +\effects +Constructs a sequence container equal to the range \tcode{rg}. +Each iterator in the range \tcode{rg} is dereferenced exactly once. + +\pnum +\ensures +\tcode{distance(begin(), end()) == ranges::distance(rg)} is \tcode{true}. +\end{itemdescr} + \begin{itemdecl} X(il) \end{itemdecl} @@ -1520,6 +1555,40 @@ \tcode{p} if \tcode{i == j}. \end{itemdescr} +\indexcont{insert_range}% +\begin{itemdecl} +a.insert_range(p, rg) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\tcode{iterator}. + +\pnum +\expects +\tcode{T} is \oldconcept{EmplaceConstructible} into \tcode{X} +from \tcode{*ranges::begin(rg)}. +For \tcode{vector} and \tcode{deque}, +\tcode{T} is also +\oldconcept{MoveInsertable} into \tcode{X}, +\oldconcept{MoveConstructible}, +\oldconcept{MoveAssignable}, and +swappable\iref{swappable.requirements}. +\tcode{rg} and \tcode{a} do not overlap. + +\pnum +\effects +Inserts copies of elements in \tcode{rg} before \tcode{p}. +Each iterator in the range \tcode{rg} is dereferenced exactly once. + +\pnum +\returns +An iterator +that points to the copy of the first element inserted into \tcode{a}, or +\tcode{p} if \tcode{rg} is empty. +\end{itemdescr} + \begin{itemdecl} a.insert(p, il) \end{itemdecl} @@ -1633,7 +1702,42 @@ referring to the elements of \tcode{a}. For \tcode{vector} and \tcode{deque}, also invalidates the past-the-end iterator. -Each iterator in the range \range{i}{j} shall be dereferenced exactly once. +Each iterator in the range \range{i}{j} is dereferenced exactly once. +\end{itemdescr} + +\indexcont{assign_range}% +\begin{itemdecl} +a.assign_range(rg) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\keyword{void} + +\pnum +\mandates +\tcode{\libconcept{assignable_from}>} +is modeled. + +\pnum +\expects +\tcode{T} is \oldconcept{EmplaceConstructible} into \tcode{X} +from \tcode{*ranges::begin(rg)}. +For \tcode{vector}, +if \tcode{R} models +neither \libconcept{sized_range} nor \libconcept{forward_range}, +\tcode{T} is also \oldconcept{MoveInsertable} into \tcode{X}. +\tcode{rg} and \tcode{a} do not overlap. + +\pnum +\effects +Replaces elements in \tcode{a} with a copy of each element in \tcode{rg}. +Invalidates all references, pointers, and iterators +referring to the elements of \tcode{a}. +For \tcode{vector} and \tcode{deque}, +also invalidates the past-the-end iterator. +Each iterator in the range \tcode{rg} is dereferenced exactly once. \end{itemdescr} \begin{itemdecl} @@ -1876,6 +1980,36 @@ \tcode{list}. \end{itemdescr} +\begin{itemdecl} +a.prepend_range(rg) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\keyword{void} + +\pnum +\expects +\tcode{T} is \oldconcept{EmplaceConstructible} into \tcode{X} +from \tcode{*ranges::begin(rg)}. + +\pnum +\effects +Inserts copies of elements in \tcode{rg} before \tcode{begin()}. +Each iterator in the range \tcode{rg} is dereferenced exactly once. +\begin{note} +The order of elements in \tcode{rg} is not reversed. +\end{note} + +\pnum +\remarks +Required for +\tcode{deque}, +\tcode{forward_list}, and +\tcode{list}. +\end{itemdescr} + \begin{itemdecl} a.push_back(t) \end{itemdecl} @@ -1928,6 +2062,36 @@ \tcode{vector}. \end{itemdescr} +\begin{itemdecl} +a.append_range(rg) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\keyword{void} + +\pnum +\expects +\tcode{T} is \oldconcept{EmplaceConstructible} into \tcode{X} +from \tcode{*ranges::begin(rg)}. +For \tcode{vector}, +\tcode{T} is also +\oldconcept{MoveInsertable} into \tcode{X}. + +\pnum +\effects +Inserts copies of elements in \tcode{rg} before \tcode{end()}. +Each iterator in the range \tcode{rg} is dereferenced exactly once. + +\pnum +\remarks +Required for +\tcode{deque}, +\tcode{list}, and +\tcode{vector}. +\end{itemdescr} + \begin{itemdecl} a.pop_front() \end{itemdecl} @@ -2460,6 +2624,9 @@ \item \range{i}{j} denotes a valid range, \item +\tcode{rg} denotes a value of a type \tcode{R} +that models \tcode{\exposconcept{container-compatible-range}}, +\item \tcode{p} denotes a valid constant iterator to \tcode{a}, \item \tcode{q} denotes a valid dereferenceable constant iterator to \tcode{a}, @@ -2713,6 +2880,59 @@ linear if \range{i}{j} is sorted with \tcode{value_comp()}. \end{itemdescr} +\indexlibraryctor{set}% +\indexlibraryctor{map}% +\indexlibraryctor{multiset}% +\indexlibraryctor{multimap}% +\begin{itemdecl} +X(from_range, rg, c) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{value_type} is +\oldconcept{EmplaceConstructible} into \tcode{X} +from \tcode{*range::begin(rg)}. + +\pnum +\effects +Constructs an empty container and +inserts each element from \tcode{rg} into it. +Uses \tcode{c} as the comparison object. + +\pnum +\complexity +$N \log N$ in general, where $N$ has the value \tcode{ranges::distance(rg)}; +linear if \tcode{rg} is sorted with \tcode{value_comp()}. +\end{itemdescr} + +\indexlibraryctor{set}% +\indexlibraryctor{map}% +\indexlibraryctor{multiset}% +\indexlibraryctor{multimap}% +\begin{itemdecl} +X(from_range, rg) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{key_compare} meets the \oldconcept{DefaultConstructible} requirements. +\tcode{value_type} is \oldconcept{EmplaceConstructible} into \tcode{X} +from \tcode{*ranges::begin(rg)}. + +\pnum +\effects +Constructs an empty container and +inserts each element from \tcode{rg} into it. +Uses \tcode{Compare()} as the comparison object. + +\pnum +\complexity +Same as \tcode{X(from_range, rg, c)}. +\end{itemdescr} + \indexlibraryctor{set}% \indexlibraryctor{map}% \indexlibraryctor{multiset}% @@ -3019,6 +3239,36 @@ $N \log (\tcode{a.size()} + N)$, where $N$ has the value \tcode{distance(i, j)}. \end{itemdescr} +\indexordmem{insert}% +\begin{itemdecl} +a.insert_range(rg) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\keyword{void} + +\pnum +\expects +\tcode{value_type} is +\oldconcept{EmplaceConstructible} into \tcode{X} +from \tcode{*ranges::begin(rg)}. +\tcode{rg} and \tcode{a} do not overlap. + +\pnum +\effects +Inserts each element from \tcode{rg} if and only if +there is no element with key equivalent to the key of that element +in containers with unique keys; +always inserts that element in containers with equivalent keys. + +\pnum +\complexity +$N \log (\tcode{a.size()} + N)$, +where $N$ has the value \tcode{ranges::distance(rg)}. +\end{itemdescr} + \indexordmem{insert}% \begin{itemdecl} a.insert(il) @@ -3625,7 +3875,8 @@ \end{itemdescr} \pnum -The \tcode{insert} and \tcode{emplace} members shall not affect the validity of +The \tcode{insert}, \tcode{insert_range}, and \tcode{emplace} members +shall not affect the validity of iterators and references to the container, and the \tcode{erase} members shall invalidate only iterators and references to the erased elements. @@ -3867,6 +4118,9 @@ \item \tcode{[i, j)} denotes a valid range, \item +\tcode{rg} denotes a value of a type \tcode{R} +that models \tcode{\exposconcept{container-compatible-range}}, +\item \tcode{p} and \tcode{q2} denote valid constant iterators to \tcode{a}, \item \tcode{q} and \tcode{q1} denote @@ -4237,6 +4491,107 @@ Average case \bigoh{N} ($N$ is \tcode{distance(i, j)}), worst case \bigoh{N^2}. \end{itemdescr} +\begin{itemdecl} +X(from_range, rg, n, hf, eq) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{value_type} is +\oldconcept{EmplaceConstructible} into \tcode{X} +from \tcode{*ranges::begin(rg)}. + +\pnum +\effects +Constructs an empty container with at least \tcode{n} buckets, +using \tcode{hf} as the hash function and +\tcode{eq} as the key equality predicate, and +inserts elements from \tcode{rg} into it. + +\pnum +\complexity +Average case \bigoh{N} ($N$ is \tcode{ranges::distance(rg)}), +worst case \bigoh{N^2}. +\end{itemdescr} + +\begin{itemdecl} +X(from_range, rg, n, hf) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{key_equal} meets the \oldconcept{DefaultConstructible} requirements. +\tcode{value_type} is +\oldconcept{\-EmplaceConstructible} into \tcode{X} +from \tcode{*ranges::begin(rg)}. + +\pnum +\effects +Constructs an empty container with at least \tcode{n} buckets, +using \tcode{hf} as the hash function and +\tcode{key_equal()} as the key equality predicate, and +inserts elements from \tcode{rg} into it. + +\pnum +\complexity +Average case \bigoh{N} ($N$ is \tcode{ranges::distance(rg)}), +worst case \bigoh{N^2}. +\end{itemdescr} + +\begin{itemdecl} +X(from_range, rg, n) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{hasher} and \tcode{key_equal} meet +the \oldconcept{DefaultConstructible} requirements. +\tcode{value_type} is +\oldconcept{EmplaceConstructible} into \tcode{X} +from \tcode{*ranges::begin(rg)}. + +\pnum +\effects +Constructs an empty container with at least \tcode{n} buckets, +using \tcode{hasher()} as the hash function and +\tcode{key_equal()} as the key equality predicate, and +inserts elements from \tcode{rg} into it. + +\pnum +\complexity +Average case \bigoh{N} ($N$ is \tcode{ranges::distance(rg)}), +worst case \bigoh{N^2}. +\end{itemdescr} + +\begin{itemdecl} +X(from_range, rg) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{hasher} and \tcode{key_equal} meet +the \oldconcept{DefaultConstructible} requirements. +\tcode{value_type} is +\oldconcept{EmplaceConstructible} into \tcode{X} +from \tcode{*ranges::begin(rg)}. + +\pnum +\effects +Constructs an empty container with an unspecified number of buckets, +using \tcode{hasher()} as the hash function and +\tcode{key_equal()} as the key equality predicate, and +inserts elements from \tcode{rg} into it. + +\pnum +\complexity +Average case \bigoh{N} ($N$ is \tcode{ranges::distance(rg)}), +worst case \bigoh{N^2}. +\end{itemdescr} + \begin{itemdecl} X(il) \end{itemdecl} @@ -4588,6 +4943,33 @@ worst case \bigoh{N(\tcode{a.size()} + 1)}. \end{itemdescr} +\indexunordmem{insert_range}% +\begin{itemdecl} +a.insert_range(rg) +\end{itemdecl} + +\begin{itemdescr} +\pnum +\result +\keyword{void} + +\pnum +\expects +\tcode{value_type} is +\oldconcept{EmplaceConstructible} into \tcode{X} +from \tcode{*ranges::begin(rg)}. +\tcode{rg} and \tcode{a} do not overlap. + +\pnum +\effects +Equivalent to \tcode{a.insert(t)} for each element \tcode{t} in \tcode{rg}. + +\pnum +\complexity +Average case \bigoh{N}, where $N$ is \tcode{ranges::distance(rg)}, +worst case \bigoh{N(\tcode{a.size()} + 1)}. +\end{itemdescr} + \indexunordmem{insert}% \begin{itemdecl} a.insert(il) @@ -5410,7 +5792,8 @@ \pnum \indextext{unordered associative containers!iterator invalidation}% -The \tcode{insert} and \tcode{emplace} members shall not affect the validity of references to +The \tcode{insert}, \tcode{insert_range}, and \tcode{emplace} members +shall not affect the validity of references to container elements, but may invalidate all iterators to the container. The \tcode{erase} members shall invalidate only iterators and references to the erased elements, and preserve the relative order of the @@ -5419,7 +5802,8 @@ \pnum \indextext{unordered associative containers!iterator invalidation}% \indextext{unordered associative containers!requirements}% -The \tcode{insert} and \tcode{emplace} members shall not affect the validity of iterators if +The \tcode{insert}, \tcode{insert_range}, and \tcode{emplace} members +shall not affect the validity of iterators if \tcode{(N+n) <= z * B}, where \tcode{N} is the number of elements in the container prior to the insert operation, \tcode{n} is the number of elements inserted, \tcode{B} is the container's bucket count, and @@ -6083,6 +6467,8 @@ deque(size_type n, const T& value, const Allocator& = Allocator()); template deque(InputIterator first, InputIterator last, const Allocator& = Allocator()); + template<@\exposconcept{container-compatible-range}@ R> + deque(from_range_t, R&& rg, const Allocator& = Allocator()); deque(const deque& x); deque(deque&&); deque(const deque&, const type_identity_t&); @@ -6096,6 +6482,8 @@ deque& operator=(initializer_list); template void assign(InputIterator first, InputIterator last); + template<@\exposconcept{container-compatible-range}@ R> + void assign_range(R&& rg); void assign(size_type n, const T& t); void assign(initializer_list); allocator_type get_allocator() const noexcept; @@ -6140,14 +6528,20 @@ void push_front(const T& x); void push_front(T&& x); + template<@\exposconcept{container-compatible-range}@ R> + void prepend_range(R&& rg); void push_back(const T& x); void push_back(T&& x); + template<@\exposconcept{container-compatible-range}@ R> + void append_range(R&& rg); iterator insert(const_iterator position, const T& x); iterator insert(const_iterator position, T&& x); iterator insert(const_iterator position, size_type n, const T& x); template iterator insert(const_iterator position, InputIterator first, InputIterator last); + template<@\exposconcept{container-compatible-range}@ R> + iterator insert_range(const_iterator position, R&& rg); iterator insert(const_iterator position, initializer_list); void pop_front(); @@ -6163,6 +6557,10 @@ template>> deque(InputIterator, InputIterator, Allocator = Allocator()) -> deque<@\placeholder{iter-value-type}@, Allocator>; + + template>> + deque(from_range_t, R&&, Allocator = Allocator()) + -> deque, Allocator>; } \end{codeblock} @@ -6247,6 +6645,23 @@ Linear in \tcode{distance(first, last)}. \end{itemdescr} +\indexlibraryctor{deque}% +\begin{itemdecl} +template<@\exposconcept{container-compatible-range}@ R> + deque(from_range_t, R&& rg, const Allocator& = Allocator()); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Constructs a \tcode{deque} with the elements of the range \tcode{rg}, +using the specified allocator. + +\pnum +\complexity +Linear in \tcode{ranges::distance(rg)}. +\end{itemdescr} + \rSec3[deque.capacity]{Capacity} \indexlibrarymember{resize}{deque}% @@ -6333,6 +6748,8 @@ template iterator insert(const_iterator position, InputIterator first, InputIterator last); +template<@\exposconcept{container-compatible-range}@ R> + iterator insert_range(const_iterator position, R&& rg); iterator insert(const_iterator position, initializer_list); template reference emplace_front(Args&&... args); @@ -6340,8 +6757,12 @@ template iterator emplace(const_iterator position, Args&&... args); void push_front(const T& x); void push_front(T&& x); +template<@\exposconcept{container-compatible-range}@ R> + void prepend_range(R&& rg); void push_back(const T& x); void push_back(T&& x); +template<@\exposconcept{container-compatible-range}@ R> + void append_range(R&& rg); \end{itemdecl} \begin{itemdescr} @@ -6509,6 +6930,8 @@ forward_list(size_type n, const T& value, const Allocator& = Allocator()); template forward_list(InputIterator first, InputIterator last, const Allocator& = Allocator()); + template<@\exposconcept{container-compatible-range}@ R> + forward_list(from_range_t, R&& rg, const Allocator& = Allocator()); forward_list(const forward_list& x); forward_list(forward_list&& x); forward_list(const forward_list& x, const type_identity_t&); @@ -6521,6 +6944,8 @@ forward_list& operator=(initializer_list); template void assign(InputIterator first, InputIterator last); + template<@\exposconcept{container-compatible-range}@ R> + void assign_range(R&& rg); void assign(size_type n, const T& t); void assign(initializer_list); allocator_type get_allocator() const noexcept; @@ -6549,6 +6974,8 @@ template reference emplace_front(Args&&... args); void push_front(const T& x); void push_front(T&& x); + template<@\exposconcept{container-compatible-range}@ R> + void prepend_range(R&& rg); void pop_front(); template iterator emplace_after(const_iterator position, Args&&... args); @@ -6559,6 +6986,8 @@ template iterator insert_after(const_iterator position, InputIterator first, InputIterator last); iterator insert_after(const_iterator position, initializer_list il); + template<@\exposconcept{container-compatible-range}@ R> + iterator insert_range_after(const_iterator position, R&& rg); iterator erase_after(const_iterator position); iterator erase_after(const_iterator position, const_iterator last); @@ -6599,6 +7028,10 @@ template>> forward_list(InputIterator, InputIterator, Allocator = Allocator()) -> forward_list<@\placeholder{iter-value-type}@, Allocator>; + + template>> + forward_list(from_range_t, R&&, Allocator = Allocator()) + -> forward_list, Allocator>; } \end{codeblock} @@ -6681,6 +7114,23 @@ Linear in \tcode{distance(first, last)}. \end{itemdescr} +\indexlibraryctor{forward_list}% +\begin{itemdecl} +template<@\exposconcept{container-compatible-range}@ R> + forward_list(from_range_t, R&& rg, const Allocator& = Allocator()); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Constructs a \tcode{forward_list} object +with the elements of the range \tcode{rg}. + +\pnum +\complexity +Linear in \tcode{ranges::distance(rg)}. +\end{itemdescr} + \rSec3[forward.list.iter]{Iterators} \indexlibrarymember{before_begin}{forward_list}% @@ -6757,6 +7207,20 @@ Inserts a copy of \tcode{x} at the beginning of the list. \end{itemdescr} +\indexlibrarymember{prepend_range}{forward_list}% +\begin{itemdecl} +template<@\exposconcept{container-compatible-range}@ R> + void prepend_range(R&& rg); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Inserts a copy of each element of \tcode{rg} at the beginning of the list. +\begin{note} +The order of elements is not reversed. +\end{note} +\end{itemdescr} \indexlibrarymember{pop}{forward_list}% \begin{itemdecl} @@ -6812,24 +7276,47 @@ \indexlibrarymember{insert_after}{forward_list}% \begin{itemdecl} -template - iterator insert_after(const_iterator position, InputIterator first, InputIterator last); +template + iterator insert_after(const_iterator position, InputIterator first, InputIterator last); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{position} is \tcode{before_begin()} or is a dereferenceable +iterator in the range \range{begin()}{end()}. +Neither \tcode{first} nor \tcode{last} are iterators in \tcode{*this}. + +\pnum +\effects +Inserts copies of elements in \range{first}{last} after \tcode{position}. + +\pnum +\returns +An iterator pointing to the last inserted element or \tcode{position} if \tcode{first == last}. +\end{itemdescr} + +\indexlibrarymember{insert_range_after}{forward_list}% +\begin{itemdecl} +template<@\exposconcept{container-compatible-range}@ R> + iterator insert_range_after(const_iterator position, R&& rg); \end{itemdecl} \begin{itemdescr} \pnum \expects -\tcode{position} is \tcode{before_begin()} or is a dereferenceable -iterator in the range \range{begin()}{end()}. -Neither \tcode{first} nor \tcode{last} are iterators in \tcode{*this}. +\tcode{position} is \tcode{before_begin()} or +is a dereferenceable iterator in the range \range{begin()}{end()}. +\tcode{rg} and \tcode{*this} do not overlap. \pnum \effects -Inserts copies of elements in \range{first}{last} after \tcode{position}. +Inserts copies of elements in the range \tcode{rg} after \tcode{position}. \pnum \returns -An iterator pointing to the last inserted element or \tcode{position} if \tcode{first == last}. +An iterator pointing to the last inserted element, +or \tcode{position} if \tcode{rg} is empty. \end{itemdescr} \indexlibrarymember{insert_after}{forward_list}% @@ -7321,6 +7808,8 @@ list(size_type n, const T& value, const Allocator& = Allocator()); template list(InputIterator first, InputIterator last, const Allocator& = Allocator()); + template<@\exposconcept{container-compatible-range}@ R> + list(from_range_t, R&& rg, const Allocator& = Allocator()); list(const list& x); list(list&& x); list(const list&, const type_identity_t&); @@ -7333,6 +7822,8 @@ list& operator=(initializer_list); template void assign(InputIterator first, InputIterator last); + template<@\exposconcept{container-compatible-range}@ R> + void assign_range(R&& rg); void assign(size_type n, const T& t); void assign(initializer_list); allocator_type get_allocator() const noexcept; @@ -7370,9 +7861,13 @@ template reference emplace_back(Args&&... args); void push_front(const T& x); void push_front(T&& x); + template<@\exposconcept{container-compatible-range}@ R> + void prepend_range(R&& rg); void pop_front(); void push_back(const T& x); void push_back(T&& x); + template<@\exposconcept{container-compatible-range}@ R> + void append_range(R&& rg); void pop_back(); template iterator emplace(const_iterator position, Args&&... args); @@ -7381,6 +7876,8 @@ iterator insert(const_iterator position, size_type n, const T& x); template iterator insert(const_iterator position, InputIterator first, InputIterator last); + template<@\exposconcept{container-compatible-range}@ R> + iterator insert_range(const_iterator position, R&& rg); iterator insert(const_iterator position, initializer_list il); iterator erase(const_iterator position); @@ -7417,6 +7914,10 @@ template>> list(InputIterator, InputIterator, Allocator = Allocator()) -> list<@\placeholder{iter-value-type}@, Allocator>; + + template>> + list(from_range_t, R&&, Allocator = Allocator()) + -> list, Allocator>; } \end{codeblock} @@ -7511,6 +8012,22 @@ \tcode{distance(first, last)}. \end{itemdescr} +\indexlibraryctor{list}% +\begin{itemdecl} +template<@\exposconcept{container-compatible-range}@ R> + list(from_range_t, R&& rg, const Allocator& = Allocator()); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Constructs a \tcode{list} object with the elements of the range \tcode{rg}. + +\pnum +\complexity +Linear in \tcode{ranges::distance(rg)}. +\end{itemdescr} + \rSec3[list.capacity]{Capacity} \indexlibrarymember{resize}{list}% @@ -7573,6 +8090,8 @@ template iterator insert(const_iterator position, InputIterator first, InputIterator last); +template<@\exposconcept{container-compatible-range}@ R> + iterator insert_range(const_iterator position, R&& rg); iterator insert(const_iterator position, initializer_list); template reference emplace_front(Args&&... args); @@ -7580,8 +8099,12 @@ template iterator emplace(const_iterator position, Args&&... args); void push_front(const T& x); void push_front(T&& x); +template<@\exposconcept{container-compatible-range}@ R> + void prepend_range(R&& rg); void push_back(const T& x); void push_back(T&& x); +template<@\exposconcept{container-compatible-range}@ R> + void append_range(R&& rg); \end{itemdecl} \begin{itemdescr} @@ -7994,7 +8517,7 @@ and, for an element type other than \tcode{bool}, of a contiguous container\iref{container.requirements.general}. The exceptions are the -\tcode{push_front}, \tcode{pop_front}, and \tcode{emplace_front} member functions, which are not +\tcode{push_front}, \tcode{prepend_range}, \tcode{pop_front}, and \tcode{emplace_front} member functions, which are not provided. Descriptions are provided here only for operations on \tcode{vector} that are not described in one of these tables or for operations where there is additional semantic information. @@ -8029,6 +8552,8 @@ constexpr vector(size_type n, const T& value, const Allocator& = Allocator()); template constexpr vector(InputIterator first, InputIterator last, const Allocator& = Allocator()); + template<@\exposconcept{container-compatible-range}@ R> + constexpr vector(from_range_t, R&& rg, const Allocator& = Allocator()); constexpr vector(const vector& x); constexpr vector(vector&&) noexcept; constexpr vector(const vector&, const type_identity_t&); @@ -8042,6 +8567,8 @@ constexpr vector& operator=(initializer_list); template constexpr void assign(InputIterator first, InputIterator last); + template<@\exposconcept{container-compatible-range}@ R> + constexpr void assign_range(R&& rg); constexpr void assign(size_type n, const T& u); constexpr void assign(initializer_list); constexpr allocator_type get_allocator() const noexcept; @@ -8089,6 +8616,8 @@ template constexpr reference emplace_back(Args&&... args); constexpr void push_back(const T& x); constexpr void push_back(T&& x); + template<@\exposconcept{container-compatible-range}@ R> + constexpr void append_range(R&& rg); constexpr void pop_back(); template constexpr iterator emplace(const_iterator position, Args&&... args); @@ -8098,6 +8627,8 @@ template constexpr iterator insert(const_iterator position, InputIterator first, InputIterator last); + template<@\exposconcept{container-compatible-range}@ R> + constexpr iterator insert_range(const_iterator position, R&& rg); constexpr iterator insert(const_iterator position, initializer_list il); constexpr iterator erase(const_iterator position); constexpr iterator erase(const_iterator first, const_iterator last); @@ -8110,6 +8641,10 @@ template>> vector(InputIterator, InputIterator, Allocator = Allocator()) -> vector<@\placeholder{iter-value-type}@, Allocator>; + + template>> + vector(from_range_t, R&&, Allocator = Allocator()) + -> vector, Allocator>; } \end{codeblock}% \indexlibrarymember{vector}{operator==}% @@ -8190,7 +8725,6 @@ \end{itemdecl} \begin{itemdescr} - \pnum \effects Constructs a \tcode{vector} equal to the @@ -8216,6 +8750,29 @@ reallocations if they are just input iterators. \end{itemdescr} +\indexlibraryctor{vector}% +\begin{itemdecl} +template<@\exposconcept{container-compatible-range}@ R> + constexpr vector(from_range_t, R&& rg, const Allocator& = Allocator()); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Constructs a \tcode{vector} object with the elements of the range \tcode{rg}, +using the specified allocator. + +\pnum +\complexity +Initializes exactly $N$ elements +from the results of dereferencing successive iterators of \tcode{rg}, +where $N$ is \tcode{ranges::distance(rg)}. +Performs no reallocations if \tcode{R} models +\tcode{ranges::\libconcept{forward_range}} or \tcode{ranges::\libconcept{sized_range}}; +otherwise, performs order $\log N$ reallocations and +order $N$ calls to the copy or move constructor of \tcode{T}. +\end{itemdescr} + \rSec3[vector.capacity]{Capacity} \indexlibrarymember{capacity}{vector}% @@ -8421,12 +8978,16 @@ constexpr iterator insert(const_iterator position, size_type n, const T& x); template constexpr iterator insert(const_iterator position, InputIterator first, InputIterator last); +template<@\exposconcept{container-compatible-range}@ R> + constexpr iterator insert_range(const_iterator position, R&& rg); constexpr iterator insert(const_iterator position, initializer_list); template constexpr reference emplace_back(Args&&... args); template constexpr iterator emplace(const_iterator position, Args&&... args); constexpr void push_back(const T& x); constexpr void push_back(T&& x); +template<@\exposconcept{container-compatible-range}@ R> + constexpr void append_range(R&& rg); \end{itemdecl} \begin{itemdescr} @@ -8574,6 +9135,8 @@ constexpr vector(size_type n, const bool& value, const Allocator& = Allocator()); template constexpr vector(InputIterator first, InputIterator last, const Allocator& = Allocator()); + template<@\exposconcept{container-compatible-range}@ R> + constexpr vector(from_range_t, R&& rg, const Allocator& = Allocator()); constexpr vector(const vector& x); constexpr vector(vector&& x); constexpr vector(const vector&, const type_identity_t&); @@ -8585,6 +9148,8 @@ constexpr vector& operator=(initializer_list); template constexpr void assign(InputIterator first, InputIterator last); + template<@\exposconcept{container-compatible-range}@ R> + constexpr void assign_range(R&& rg); constexpr void assign(size_type n, const bool& t); constexpr void assign(initializer_list); constexpr allocator_type get_allocator() const noexcept; @@ -8626,6 +9191,8 @@ // modifiers template constexpr reference emplace_back(Args&&... args); constexpr void push_back(const bool& x); + template<@\exposconcept{container-compatible-range}@ R> + constexpr void append_range(R&& rg); constexpr void pop_back(); template constexpr iterator emplace(const_iterator position, Args&&... args); constexpr iterator insert(const_iterator position, const bool& x); @@ -8633,6 +9200,8 @@ template constexpr iterator insert(const_iterator position, InputIterator first, InputIterator last); + template<@\exposconcept{container-compatible-range}@ R> + constexpr iterator insert_range(const_iterator position, R&& rg); constexpr iterator insert(const_iterator position, initializer_list il); constexpr iterator erase(const_iterator position); @@ -8729,6 +9298,15 @@ using @\placeholder{iter-to-alloc-type}@ = pair< add_const_t::value_type::first_type>, typename iterator_traits::value_type::second_type>; // \expos +template + using @\exposid{range-key-type}@ = + remove_const_t::first_type>; // \expos +template + using @\exposid{range-mapped-type}@ = typename ranges::range_value_t::second_type; // \expos +template + using @\exposid{range-to-alloc-type}@ = + pair::first_type>, + typename ranges::range_value_t::second_type>; // \expos \end{codeblock} \rSec2[associative.map.syn]{Header \tcode{} synopsis} @@ -8941,6 +9519,8 @@ template map(InputIterator first, InputIterator last, const Compare& comp = Compare(), const Allocator& = Allocator()); + template<@\exposconcept{container-compatible-range}@ R> + map(from_range_t, R&& rg, const Compare& comp = Compare(), const Allocator& = Allocator()); map(const map& x); map(map&& x); explicit map(const Allocator&); @@ -8952,6 +9532,9 @@ template map(InputIterator first, InputIterator last, const Allocator& a) : map(first, last, Compare(), a) { } + template<@\exposconcept{container-compatible-range}@ R> + map(from_range_t, R&& rg, const Allocator& a)) + : map(from_range, std::forward(rg), Compare(), a) { } map(initializer_list il, const Allocator& a) : map(il, Compare(), a) { } ~map(); @@ -9001,6 +9584,8 @@ iterator insert(const_iterator position, P&&); template void insert(InputIterator first, InputIterator last); + template<@\exposconcept{container-compatible-range}@ R> + void insert_range(R&& rg); void insert(initializer_list); node_type extract(const_iterator position); @@ -9084,6 +9669,11 @@ map(InputIterator, InputIterator, Compare = Compare(), Allocator = Allocator()) -> map<@\placeholder{iter-key-type}@, @\placeholder{iter-mapped-type}@, Compare, Allocator>; + template, + class Allocator = allocator<@\exposid{range-to-alloc-type}@>> + map(from_range_t, R&&, Compare = Compare(), Allocator = Allocator()) + -> map<@\exposid{range-key-type}@, @\exposid{range-mapped-type}@, Compare, Allocator>; + template, class Allocator = allocator>> map(initializer_list>, Compare = Compare(), Allocator = Allocator()) @@ -9094,6 +9684,10 @@ -> map<@\placeholder{iter-key-type}@, @\placeholder{iter-mapped-type}@, less<@\placeholder{iter-key-type}@>, Allocator>; + template + map(from_range_t, R&&, Allocator) + -> map<@\exposid{range-key-type}@, @\exposid{range-mapped-type}@, less<@\exposid{range-key-type}@>, Allocator>; + template map(initializer_list>, Allocator) -> map, Allocator>; } @@ -9146,6 +9740,25 @@ is \tcode{last - first}. \end{itemdescr} +\indexlibraryctor{map}% +\begin{itemdecl} +template<@\exposconcept{container-compatible-range}@ R> + map(from_range_t, R&& rg, const Compare& comp = Compare(), const Allocator& = Allocator()); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Constructs an empty \tcode{map} +using the specified comparison object and allocator, +and inserts elements from the range \tcode{rg}. + +\pnum +\complexity +Linear in $N$ if \tcode{rg} is already sorted using \tcode{comp} and +otherwise $N \log N$, where $N$ is \tcode{ranges::distance(rg)}. +\end{itemdescr} + \rSec3[map.access]{Element access} \indexlibrary{\idxcode{operator[]}!\idxcode{map}}% @@ -9489,6 +10102,9 @@ multimap(InputIterator first, InputIterator last, const Compare& comp = Compare(), const Allocator& = Allocator()); + template<@\exposconcept{container-compatible-range}@ R> + multimap(from_range_t, R&& rg, + const Compare& comp = Compare(), const Allocator& = Allocator()); multimap(const multimap& x); multimap(multimap&& x); explicit multimap(const Allocator&); @@ -9500,6 +10116,9 @@ template multimap(InputIterator first, InputIterator last, const Allocator& a) : multimap(first, last, Compare(), a) { } + template<@\exposconcept{container-compatible-range}@ R> + multimap(from_range_t, R&& rg, const Allocator& a)) + : multimap(from_range, std::forward(rg), Compare(), a) { } multimap(initializer_list il, const Allocator& a) : multimap(il, Compare(), a) { } ~multimap(); @@ -9542,6 +10161,8 @@ template iterator insert(const_iterator position, P&& x); template void insert(InputIterator first, InputIterator last); + template<@\exposconcept{container-compatible-range}@ R> + void insert_range(R&& rg); void insert(initializer_list); node_type extract(const_iterator position); @@ -9609,6 +10230,11 @@ -> multimap<@\placeholder{iter-key-type}@, @\placeholder{iter-mapped-type}@, Compare, Allocator>; + template>, + class Allocator = allocator<@\exposid{range-to-alloc-type}@>> + multimap(from_range_t, R&&, Compare = Compare(), Allocator = Allocator()) + -> multimap<@\exposid{range-key-type}@, @\exposid{range-mapped-type}@, Compare, Allocator>; + template, class Allocator = allocator>> multimap(initializer_list>, Compare = Compare(), Allocator = Allocator()) @@ -9619,6 +10245,10 @@ -> multimap<@\placeholder{iter-key-type}@, @\placeholder{iter-mapped-type}@, less<@\placeholder{iter-key-type}@>, Allocator>; + template + multimap(from_range_t, R&&, Allocator) + -> multimap<@\exposid{range-key-type}@, @\exposid{range-mapped-type}@, less<@\exposid{range-key-type}@>, Allocator>; + template multimap(initializer_list>, Allocator) -> multimap, Allocator>; @@ -9673,6 +10303,25 @@ \tcode{last - first}. \end{itemdescr} +\indexlibraryctor{multimap}% +\begin{itemdecl} +template<@\exposconcept{container-compatible-range}@ R> + multimap(from_range_t, R&& rg, const Compare& comp = Compare(), const Allocator& = Allocator()); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Constructs an empty \tcode{multimap} +using the specified comparison object and allocator, and +inserts elements from the range \tcode{rg}. + +\pnum +\complexity +Linear in $N$ if \tcode{rg} is already sorted using \tcode{comp} and +otherwise $N \log N$, where $N$ is \tcode{ranges::distance(rg)}. +\end{itemdescr} + \rSec3[multimap.modifiers]{Modifiers} \indexlibrarymember{insert}{multimap}% @@ -9795,6 +10444,8 @@ template set(InputIterator first, InputIterator last, const Compare& comp = Compare(), const Allocator& = Allocator()); + template<@\exposconcept{container-compatible-range}@ R> + set(from_range_t, R&& rg, const Compare& comp = Compare(), const Allocator& = Allocator()); set(const set& x); set(set&& x); explicit set(const Allocator&); @@ -9805,6 +10456,9 @@ template set(InputIterator first, InputIterator last, const Allocator& a) : set(first, last, Compare(), a) { } + template<@\exposconcept{container-compatible-range}@ R> + set(from_range_t, R&& rg, const Allocator& a)) + : set(from_range, std::forward(rg), Compare(), a) { } set(initializer_list il, const Allocator& a) : set(il, Compare(), a) { } ~set(); @@ -9845,6 +10499,8 @@ iterator insert(const_iterator position, value_type&& x); template void insert(InputIterator first, InputIterator last); + template<@\exposconcept{container-compatible-range}@ R> + void insert_range(R&& rg); void insert(initializer_list); node_type extract(const_iterator position); @@ -9913,6 +10569,11 @@ Compare = Compare(), Allocator = Allocator()) -> set<@\placeholder{iter-value-type}@, Compare, Allocator>; + template>, + class Allocator = allocator>> + set(from_range_t, R&&, Compare = Compare(), Allocator = Allocator()) + -> set, Compare, Allocator>; + template, class Allocator = allocator> set(initializer_list, Compare = Compare(), Allocator = Allocator()) -> set; @@ -9922,6 +10583,10 @@ -> set<@\placeholder{iter-value-type}@, less<@\placeholder{iter-value-type}@>, Allocator>; + template + set(from_range_t, R&&, Allocator) + -> set, less>, Allocator>; + template set(initializer_list, Allocator) -> set, Allocator>; } @@ -9972,6 +10637,24 @@ \tcode{last - first}. \end{itemdescr} +\indexlibraryctor{set}% +\begin{itemdecl} +template<@\exposconcept{container-compatible-range}@ R> + set(from_range_t, R&& rg, const Compare& comp = Compare(), const Allocator& = Allocator()); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Constructs an empty \tcode{set} using the specified comparison object and allocator, +and inserts elements from the range \tcode{rg}. + +\pnum +\complexity +Linear in $N$ if \tcode{rg} is already sorted using \tcode{comp} and +otherwise $N \log N$, where $N$ is \tcode{ranges::distance(rg)}. +\end{itemdescr} + \rSec3[set.erasure]{Erasure} \indexlibrarymember{erase_if}{set}% @@ -10072,6 +10755,9 @@ template multiset(InputIterator first, InputIterator last, const Compare& comp = Compare(), const Allocator& = Allocator()); + template<@\exposconcept{container-compatible-range}@ R> + multiset(from_range_t, R&& rg, + const Compare& comp = Compare(), const Allocator& = Allocator()); multiset(const multiset& x); multiset(multiset&& x); explicit multiset(const Allocator&); @@ -10082,6 +10768,9 @@ template multiset(InputIterator first, InputIterator last, const Allocator& a) : multiset(first, last, Compare(), a) { } + template<@\exposconcept{container-compatible-range}@ R> + multiset(from_range_t, R&& rg, const Allocator& a)) + : multiset(from_range, std::forward(rg), Compare(), a) { } multiset(initializer_list il, const Allocator& a) : multiset(il, Compare(), a) { } ~multiset(); @@ -10122,6 +10811,8 @@ iterator insert(const_iterator position, value_type&& x); template void insert(InputIterator first, InputIterator last); + template<@\exposconcept{container-compatible-range}@ R> + void insert_range(R&& rg); void insert(initializer_list); node_type extract(const_iterator position); @@ -10190,6 +10881,11 @@ Compare = Compare(), Allocator = Allocator()) -> multiset<@\placeholder{iter-value-type}@, Compare, Allocator>; + template>, + class Allocator = allocator>> + multiset(from_range_t, R&&, Compare = Compare(), Allocator = Allocator()) + -> multiset, Compare, Allocator>; + template, class Allocator = allocator> multiset(initializer_list, Compare = Compare(), Allocator = Allocator()) -> multiset; @@ -10199,6 +10895,10 @@ -> multiset<@\placeholder{iter-value-type}@, less<@\placeholder{iter-value-type}@>, Allocator>; + template + multiset(from_range_t, R&&, Allocator) + -> multiset, less>, Allocator>; + template multiset(initializer_list, Allocator) -> multiset, Allocator>; } @@ -10249,6 +10949,25 @@ \tcode{last - first}. \end{itemdescr} +\indexlibraryctor{multiset}% +\begin{itemdecl} +template<@\exposconcept{container-compatible-range}@ R> + multiset(from_range_t, R&& rg, const Compare& comp = Compare(), const Allocator& = Allocator()); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Constructs an empty \tcode{multiset} +using the specified comparison object and allocator, and +inserts elements from the range \tcode{rg}. + +\pnum +\complexity +Linear in $N$ if \tcode{rg} is already sorted using \tcode{comp} and +otherwise $N \log N$, where $N$ is \tcode{ranges::distance(rg)}. +\end{itemdescr} + \rSec3[multiset.erasure]{Erasure} \indexlibrarymember{erase_if}{multiset}% @@ -10499,6 +11218,11 @@ const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type()); + + template<@\exposconcept{container-compatible-range}@ R> + unordered_map(from_range_t, R&& rg, size_type n = @\seebelow@, + const hasher& hf = hasher(), const key_equal& eql = key_equal(), + const allocator_type& a = allocator_type()); unordered_map(const unordered_map&); unordered_map(unordered_map&&); explicit unordered_map(const Allocator&); @@ -10520,6 +11244,12 @@ unordered_map(InputIterator f, InputIterator l, size_type n, const hasher& hf, const allocator_type& a) : unordered_map(f, l, n, hf, key_equal(), a) { } + template<@\exposconcept{container-compatible-range}@ R> + unordered_map(from_range_t, R&& rg, size_type n, const allocator_type& a) + : unordered_map(from_range, std::forward(rg), n, hasher(), key_equal(), a) { } + template<@\exposconcept{container-compatible-range}@ R> + unordered_map(from_range_t, R&& rg, size_type n, const hasher& hf, const allocator_type& a) + : unordered_map(from_range, std::forward(rg), n, hf, key_equal(), a) { } unordered_map(initializer_list il, size_type n, const allocator_type& a) : unordered_map(il, n, hasher(), key_equal(), a) { } unordered_map(initializer_list il, size_type n, const hasher& hf, @@ -10557,6 +11287,8 @@ iterator insert(const_iterator hint, value_type&& obj); template iterator insert(const_iterator hint, P&& obj); template void insert(InputIterator first, InputIterator last); + template<@\exposconcept{container-compatible-range}@ R> + void insert_range(R&& rg); void insert(initializer_list); node_type extract(const_iterator position); @@ -10662,6 +11394,13 @@ -> unordered_map<@\placeholder{iter-key-type}@, @\placeholder{iter-mapped-type}@, Hash, Pred, Allocator>; + template>, + class Pred = equal_to<@\exposid{range-key-type}@>, + class Allocator = allocator<@\exposid{range-to-alloc-type}@>> + unordered_map(from_range_t, R&&, typename @\seebelow@::size_type = @\seebelow@, + Hash = Hash(), Pred = Pred(), Allocator = Allocator()) + -> unordered_map<@\exposid{range-key-type}@, @\exposid{range-mapped-type}@, Hash, Pred, Allocator>; + template, class Pred = equal_to, class Allocator = allocator>> unordered_map(initializer_list>, @@ -10686,6 +11425,21 @@ -> unordered_map<@\placeholder{iter-key-type}@, @\placeholder{iter-mapped-type}@, Hash, equal_to<@\placeholder{iter-key-type}@>, Allocator>; + template + unordered_map(from_range_t, R&&, typename @\seebelow@::size_type, Allocator) + -> unordered_map<@\exposid{range-key-type}@, @\exposid{range-mapped-type}@, hash<@\exposid{range-key-type}@>, + equal_to<@\exposid{range-key-type}@>, Allocator>; + + template + unordered_map(from_range_t, R&&, Allocator) + -> unordered_map<@\exposid{range-key-type}@, @\exposid{range-mapped-type}@, hash<@\exposid{range-key-type}@>, + equal_to<@\exposid{range-key-type}@>, Allocator>; + + template + unordered_map(from_range_t, R&&, typename @\seebelow@::size_type, Hash, Allocator) + -> unordered_map<@\exposid{range-key-type}@, @\exposid{range-mapped-type}@, Hash, + equal_to<@\exposid{range-key-type}@>, Allocator>; + template unordered_map(initializer_list>, typename @\seebelow@::size_type, Allocator) @@ -10740,6 +11494,12 @@ const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type()); +template<@\exposconcept{container-compatible-range}@ R> + unordered_map(from_range_t, R&& rg, + size_type n = @\seebelow@, + const hasher& hf = hasher(), + const key_equal& eql = key_equal(), + const allocator_type& a = allocator_type()); unordered_map(initializer_list il, size_type n = @\seebelow@, const hasher& hf = hasher(), @@ -10755,9 +11515,8 @@ using at least \tcode{n} buckets. If \tcode{n} is not provided, the number of buckets is \impldef{default number of buckets in \tcode{unordered_map}}. Then -inserts elements from the range \range{f}{l} -for the first form, or from the range -\range{il.begin()}{il.end()} for the second form. +inserts elements from the range \range{f}{l}, \tcode{rg}, or \tcode{il}, +respectively. \tcode{max_load_factor()} returns \tcode{1.0}. \pnum @@ -11098,6 +11857,12 @@ const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type()); + template<@\exposconcept{container-compatible-range}@ R> + unordered_multimap(from_range_t, R&& rg, + size_type n = @\seebelow@, + const hasher& hf = hasher(), + const key_equal& eql = key_equal(), + const allocator_type& a = allocator_type()); unordered_multimap(const unordered_multimap&); unordered_multimap(unordered_multimap&&); explicit unordered_multimap(const Allocator&); @@ -11119,6 +11884,14 @@ unordered_multimap(InputIterator f, InputIterator l, size_type n, const hasher& hf, const allocator_type& a) : unordered_multimap(f, l, n, hf, key_equal(), a) { } + template<@\exposconcept{container-compatible-range}@ R> + unordered_multimap(from_range_t, R&& rg, size_type n, const allocator_type& a) + : unordered_multimap(from_range, std::forward(rg), + n, hasher(), key_equal(), a) { } + template<@\exposconcept{container-compatible-range}@ R> + unordered_multimap(from_range_t, R&& rg, size_type n, const hasher& hf, + const allocator_type& a) + : unordered_multimap(from_range, std::forward(rg), n, hf, key_equal(), a) { } unordered_multimap(initializer_list il, size_type n, const allocator_type& a) : unordered_multimap(il, n, hasher(), key_equal(), a) { } unordered_multimap(initializer_list il, size_type n, const hasher& hf, @@ -11156,6 +11929,8 @@ iterator insert(const_iterator hint, value_type&& obj); template iterator insert(const_iterator hint, P&& obj); template void insert(InputIterator first, InputIterator last); + template<@\exposconcept{container-compatible-range}@ R> + void insert_range(R&& rg); void insert(initializer_list); node_type extract(const_iterator position); @@ -11238,6 +12013,14 @@ -> unordered_multimap<@\placeholder{iter-key-type}@, @\placeholder{iter-mapped-type}@, Hash, Pred, Allocator>; + template>, + class Pred = equal_to<@\exposid{range-key-type}@>, + class Allocator = allocator<@\exposid{range-to-alloc-type}@>> + unordered_multimap(from_range_t, R&&, typename @\seebelow@::size_type = @\seebelow@, + Hash = Hash(), Pred = Pred(), Allocator = Allocator()) + -> unordered_multimap<@\exposid{range-key-type}@, @\exposid{range-mapped-type}@, Hash, Pred, Allocator>; + template, class Pred = equal_to, class Allocator = allocator>> unordered_multimap(initializer_list>, @@ -11263,6 +12046,21 @@ -> unordered_multimap<@\placeholder{iter-key-type}@, @\placeholder{iter-mapped-type}@, Hash, equal_to<@\placeholder{iter-key-type}@>, Allocator>; + template + unordered_multimap(from_range_t, R&&, typename @\seebelow@::size_type, Allocator) + -> unordered_multimap<@\exposid{range-key-type}@, @\exposid{range-mapped-type}@, hash<@\exposid{range-key-type}@>, + equal_to<@\exposid{range-key-type}@>, Allocator>; + + template + unordered_multimap(from_range_t, R&&, Allocator) + -> unordered_multimap<@\exposid{range-key-type}@, @\exposid{range-mapped-type}@, hash<@\exposid{range-key-type}@>, + equal_to<@\exposid{range-key-type}@>, Allocator>; + + template + unordered_multimap(from_range_t, R&&, typename @\seebelow@::size_type, Hash, Allocator) + -> unordered_multimap<@\exposid{range-key-type}@, @\exposid{range-mapped-type}@, Hash, + equal_to<@\exposid{range-key-type}@>, Allocator>; + template unordered_multimap(initializer_list>, typename @\seebelow@::size_type, Allocator) @@ -11317,6 +12115,12 @@ const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type()); +template<@\exposconcept{container-compatible-range}@ R> + unordered_multimap(from_range_t, R&& rg, + size_type n = @\seebelow@, + const hasher& hf = hasher(), + const key_equal& eql = key_equal(), + const allocator_type& a = allocator_type()); unordered_multimap(initializer_list il, size_type n = @\seebelow@, const hasher& hf = hasher(), @@ -11332,9 +12136,8 @@ using at least \tcode{n} buckets. If \tcode{n} is not provided, the number of buckets is \impldef{default number of buckets in \tcode{unordered_multimap}}. Then -inserts elements from the range \range{f}{l} -for the first form, or from the range -\range{il.begin()}{il.end()} for the second form. +inserts elements from the range \range{f}{l}, \tcode{rg}, or \tcode{il}, +respectively. \tcode{max_load_factor()} returns \tcode{1.0}. \pnum @@ -11471,6 +12274,12 @@ const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type()); + template<@\exposconcept{container-compatible-range}@ R> + unordered_set(from_range_t, R&& rg, + size_type n = @\seebelow@, + const hasher& hf = hasher(), + const key_equal& eql = key_equal(), + const allocator_type& a = allocator_type()); unordered_set(const unordered_set&); unordered_set(unordered_set&&); explicit unordered_set(const Allocator&); @@ -11494,6 +12303,12 @@ : unordered_set(f, l, n, hf, key_equal(), a) { } unordered_set(initializer_list il, size_type n, const allocator_type& a) : unordered_set(il, n, hasher(), key_equal(), a) { } + template<@\exposconcept{container-compatible-range}@ R> + unordered_set(from_range_t, R&& rg, size_type n, const allocator_type& a) + : unordered_set(from_range, std::forward(rg), n, hasher(), key_equal(), a) { } + template<@\exposconcept{container-compatible-range}@ R> + unordered_set(from_range_t, R&& rg, size_type n, const hasher& hf, const allocator_type& a) + : unordered_set(from_range, std::forward(rg), n, hf, key_equal(), a) { } unordered_set(initializer_list il, size_type n, const hasher& hf, const allocator_type& a) : unordered_set(il, n, hf, key_equal(), a) { } @@ -11527,6 +12342,8 @@ iterator insert(const_iterator hint, const value_type& obj); iterator insert(const_iterator hint, value_type&& obj); template void insert(InputIterator first, InputIterator last); + template<@\exposconcept{container-compatible-range}@ R> + void insert_range(R&& rg); void insert(initializer_list); node_type extract(const_iterator position); @@ -11608,6 +12425,14 @@ -> unordered_set<@\placeholder{iter-value-type}@, Hash, Pred, Allocator>; + template>, + class Pred = equal_to>, + class Allocator = allocator>> + unordered_set(from_range_t, R&&, typename @\seebelow@::size_type = @\seebelow@, +Hash = Hash(), Pred = Pred(), Allocator = Allocator()) + -> unordered_set, Hash, Pred, Allocator>; + template, class Pred = equal_to, class Allocator = allocator> unordered_set(initializer_list, typename @\seebelow@::size_type = @\seebelow@, @@ -11628,6 +12453,21 @@ equal_to<@\placeholder{iter-value-type}@>, Allocator>; + template + unordered_set(from_range_t, R&&, typename @\seebelow@::size_type, Allocator) + -> unordered_set, hash>, + equal_to>, Allocator>; + + template + unordered_set(from_range_t, R&&, Allocator) + -> unordered_set, hash>, + equal_to>, Allocator>; + + template + unordered_set(from_range_t, R&&, typename @\seebelow@::size_type, Hash, Allocator) + -> unordered_set, Hash, + equal_to>, Allocator>; + template unordered_set(initializer_list, typename @\seebelow@::size_type, Allocator) -> unordered_set, equal_to, Allocator>; @@ -11677,6 +12517,12 @@ const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type()); +template<@\exposconcept{container-compatible-range}@ R> + unordered_multiset(from_range_t, R&& rg, + size_type n = @\seebelow@, + const hasher& hf = hasher(), + const key_equal& eql = key_equal(), + const allocator_type& a = allocator_type()); unordered_set(initializer_list il, size_type n = @\seebelow@, const hasher& hf = hasher(), @@ -11692,9 +12538,8 @@ using at least \tcode{n} buckets. If \tcode{n} is not provided, the number of buckets is \impldef{default number of buckets in \tcode{unordered_set}}. Then -inserts elements from the range \range{f}{l} -for the first form, or from the range -\range{il.begin()}{il.end()} for the second form. +inserts elements from the range \range{f}{l}, \tcode{rg}, or \tcode{il}, +respectively. \tcode{max_load_factor()} returns \tcode{1.0}. \pnum @@ -11800,6 +12645,12 @@ const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type()); + template<@\exposconcept{container-compatible-range}@ R> + unordered_multiset(from_range_t, R&& rg, + size_type n = @\seebelow@, + const hasher& hf = hasher(), + const key_equal& eql = key_equal(), + const allocator_type& a = allocator_type()); unordered_multiset(const unordered_multiset&); unordered_multiset(unordered_multiset&&); explicit unordered_multiset(const Allocator&); @@ -11821,6 +12672,14 @@ unordered_multiset(InputIterator f, InputIterator l, size_type n, const hasher& hf, const allocator_type& a) : unordered_multiset(f, l, n, hf, key_equal(), a) { } + template<@\exposconcept{container-compatible-range}@ R> + unordered_multiset(from_range_t, R&& rg, size_type n, const allocator_type& a) + : unordered_multiset(from_range, std::forward(rg), + n, hasher(), key_equal(), a) { } + template<@\exposconcept{container-compatible-range}@ R> + unordered_multiset(from_range_t, R&& rg, size_type n, const hasher& hf, + const allocator_type& a) + : unordered_multiset(from_range, std::forward(rg), n, hf, key_equal(), a) { } unordered_multiset(initializer_list il, size_type n, const allocator_type& a) : unordered_multiset(il, n, hasher(), key_equal(), a) { } unordered_multiset(initializer_list il, size_type n, const hasher& hf, @@ -11856,6 +12715,8 @@ iterator insert(const_iterator hint, const value_type& obj); iterator insert(const_iterator hint, value_type&& obj); template void insert(InputIterator first, InputIterator last); + template<@\exposconcept{container-compatible-range}@ R> + void insert_range(R&& rg); void insert(initializer_list); node_type extract(const_iterator position); @@ -11937,6 +12798,14 @@ -> unordered_multiset<@\placeholder{iter-value-type}@, Hash, Pred, Allocator>; + template>, + class Pred = equal_to>, + class Allocator = allocator>> + unordered_multiset(from_range_t, R&&, typename @\seebelow@::size_type = @\seebelow@, + Hash = Hash(), Pred = Pred(), Allocator = Allocator()) + -> unordered_multiset, Hash, Pred, Allocator>; + template, class Pred = equal_to, class Allocator = allocator> unordered_multiset(initializer_list, typename @\seebelow@::size_type = @\seebelow@, @@ -11957,6 +12826,21 @@ equal_to<@\placeholder{iter-value-type}@>, Allocator>; + template + unordered_multiset(from_range_t, R&&, typename @\seebelow@::size_type, Allocator) + -> unordered_multiset, hash>, + equal_to>, Allocator>; + + template + unordered_multiset(from_range_t, R&&, Allocator) + -> unordered_multiset, hash>, + equal_to>, Allocator>; + + template + unordered_multiset(from_range_t, R&&, typename @\seebelow@::size_type, Hash, Allocator) + -> unordered_multiset, Hash, equal_to>, + Allocator>; + template unordered_multiset(initializer_list, typename @\seebelow@::size_type, Allocator) -> unordered_multiset, equal_to, Allocator>; @@ -12006,6 +12890,12 @@ const hasher& hf = hasher(), const key_equal& eql = key_equal(), const allocator_type& a = allocator_type()); +template<@\exposconcept{container-compatible-range}@ R> + unordered_multiset(from_range_t, R&& rg, + size_type n = @\seebelow@, + const hasher& hf = hasher(), + const key_equal& eql = key_equal(), + const allocator_type& a = allocator_type()); unordered_multiset(initializer_list il, size_type n = @\seebelow@, const hasher& hf = hasher(), @@ -12021,9 +12911,8 @@ using at least \tcode{n} buckets. If \tcode{n} is not provided, the number of buckets is \impldef{default number of buckets in \tcode{unordered_multiset}}. Then -inserts elements from the range \range{f}{l} -for the first form, or from the range -\range{il.begin()}{il.end()} for the second form. +inserts elements from the range \range{f}{l}, \tcode{rg}, or \tcode{il}, +respectively. \tcode{max_load_factor()} returns \tcode{1.0}. \pnum @@ -12215,6 +13104,7 @@ explicit queue(const Container&); explicit queue(Container&&); template queue(InputIterator first, InputIterator last); + template<@\exposconcept{container-compatible-range}@ R> queue(from_range_t, R&& rg); template explicit queue(const Alloc&); template queue(const Container&, const Alloc&); template queue(Container&&, const Alloc&); @@ -12222,6 +13112,8 @@ template queue(queue&&, const Alloc&); template queue(InputIterator first, InputIterator last, const Alloc&); + template<@\exposconcept{container-compatible-range}@ R, class Alloc> + queue(from_range_t, R&& rg, const Alloc&); [[nodiscard]] bool empty() const { return c.empty(); } size_type size() const { return c.size(); } @@ -12231,6 +13123,7 @@ const_reference back() const { return c.back(); } void push(const value_type& x) { c.push_back(x); } void push(value_type&& x) { c.push_back(std::move(x)); } + template<@\exposconcept{container-compatible-range}@ R> void push_range(R&& rg); template decltype(auto) emplace(Args&&... args) { return c.emplace_back(std::forward(args)...); } @@ -12245,6 +13138,9 @@ template queue(InputIterator, InputIterator) -> queue<@\exposid{iter-value-type}@>; + template + queue(from_range_t, R&&) -> queue>; + template queue(Container, Allocator) -> queue; @@ -12253,6 +13149,10 @@ -> queue<@\exposid{iter-value-type}@, deque<@\exposid{iter-value-type}@, Allocator>>; + template + queue(from_range_t, R&&, Allocator) + -> queue, deque, Allocator>>; + template struct uses_allocator, Alloc> : uses_allocator::type { }; @@ -12296,6 +13196,18 @@ \tcode{first} as the first argument and \tcode{last} as the second argument. \end{itemdescr} +\indexlibraryctor{queue}% +\begin{itemdecl} +template<@\exposconcept{container-compatible-range}@ R> + queue(from_range_t, R&& rg); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \tcode{c} with \tcode{ranges::to(std::forward(rg))}. +\end{itemdescr} + \rSec3[queue.cons.alloc]{Constructors with allocators} \pnum @@ -12376,6 +13288,35 @@ \tcode{alloc} as the third argument. \end{itemdescr} +\indexlibraryctor{queue}% +\begin{itemdecl} +template<@\exposconcept{container-compatible-range}@ R, class Alloc> + queue(from_range_t, R&& rg, const Alloc& a); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \tcode{c} with +\tcode{ranges::to(std::forward(rg), a)}. +\end{itemdescr} + +\rSec3[queue.mod]{Modifiers} + +\indexlibrarymember{push_range}{queue}% +\begin{itemdecl} +template<@\exposconcept{container-compatible-range}@ R> + void push_range(R&& rg); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to \tcode{c.append_range(std::forward(rg))} +if that is a valid expression, +otherwise \tcode{ranges::copy(rg, back_inserter(c))}. +\end{itemdescr} + \rSec3[queue.ops]{Operators} \indexlibrarymember{operator==}{queue}% @@ -12536,6 +13477,8 @@ template priority_queue(InputIterator first, InputIterator last, const Compare& x, Container&&); + template<@\exposconcept{container-compatible-range}@ R> + priority_queue(from_range_t, R&& rg, const Compare& x = Compare()); template explicit priority_queue(const Alloc&); template priority_queue(const Compare&, const Alloc&); template priority_queue(const Compare&, const Container&, const Alloc&); @@ -12551,12 +13494,18 @@ const Alloc&); template priority_queue(InputIterator, InputIterator, const Compare&, Container&&, const Alloc&); + template<@\exposconcept{container-compatible-range}@ R, class Alloc> + priority_queue(from_range_t, R&& rg, const Compare&, const Alloc&); + template<@\exposconcept{container-compatible-range}@ R, class Alloc> + priority_queue(from_range_t, R&& rg, const Alloc&); [[nodiscard]] bool empty() const { return c.empty(); } size_type size() const { return c.size(); } const_reference top() const { return c.front(); } void push(const value_type& x); void push(value_type&& x); + template<@\exposconcept{container-compatible-range}@ R> + void push_range(R&& rg); template void emplace(Args&&... args); void pop(); void swap(priority_queue& q) noexcept(is_nothrow_swappable_v && @@ -12574,6 +13523,10 @@ priority_queue(InputIterator, InputIterator, Compare = Compare(), Container = Container()) -> priority_queue<@\exposid{iter-value-type}@, Container, Compare>; + template> + priority_queue(from_range_t, R&&, Compare = Compare()) + -> priority_queue, vector>, Compare>; + template priority_queue(Compare, Container, Allocator) -> priority_queue; @@ -12593,6 +13546,15 @@ priority_queue(InputIterator, InputIterator, Compare, Container, Allocator) -> priority_queue; + template + priority_queue(from_range_t, R&&, Compare, Allocator) + -> priority_queue, vector, Allocator>, + Compare>; + + template + priority_queue(from_range_t, R&&, Allocator) + -> priority_queue, vector, Allocator>>; + // no equality is provided template @@ -12671,6 +13633,24 @@ \tcode{make_heap(c.begin(), c.end(), comp)}. \end{itemdescr} +\indexlibraryctor{priority_queue}% +\begin{itemdecl} +template<@\exposconcept{container-compatible-range}@ R> + priority_queue(from_range_t, R&& rg, const Compare& x = Compare()); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{x} defines a strict weak ordering\iref{alg.sorting}. + +\pnum +\effects +Initializes \tcode{comp} with \tcode{x} and +\tcode{c} with \tcode{ranges::to(std::forward(rg))} and +finally calls \tcode{make_heap(c.begin(), c.end(), comp)}. +\end{itemdescr} + \rSec3[priqueue.cons.alloc]{Constructors with allocators} \pnum @@ -12820,6 +13800,34 @@ finally calls \tcode{make_heap(c.begin(), c.end(), comp)}. \end{itemdescr} +\indexlibraryctor{priority_queue}% +\begin{itemdecl} +template<@\exposconcept{container-compatible-range}@ R, class Alloc> + priority_queue(from_range_t, R&& rg, const Compare& compare, const Alloc& a); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \tcode{comp} with \tcode{compare} and +\tcode{c} with \tcode{ranges::to(std::forward(rg), a)}; +calls \tcode{make_heap(c.begin(), c.end(), comp)}. +\end{itemdescr} + +\indexlibraryctor{priority_queue}% +\begin{itemdecl} +template<@\exposconcept{container-compatible-range}@ R, class Alloc> + priority_queue(from_range_t, R&& rg, const Alloc& a); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes +\tcode{c} with \tcode{ranges::to(std::forward(rg), a)}; +calls \tcode{make_heap(c.\linebreak begin(), c.end(), comp)}. +\end{itemdescr} + \rSec3[priqueue.members]{Members} \indexlibrarymember{push}{priority_queue}% @@ -12852,6 +13860,22 @@ \end{codeblock} \end{itemdescr} +\indexlibrarymember{push_range}{priority_queue}% +\begin{itemdecl} +template<@\exposconcept{container-compatible-range}@ R> + void push_range(R&& rg); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Insert all elements of \tcode{rg} in \tcode{c}. + +\pnum +\ensures +\tcode{is_heap(c.begin(), c.end(), comp)} is \tcode{true}. +\end{itemdescr} + \indexlibrarymember{emplace}{priority_queue}% \begin{itemdecl} template void emplace(Args&&... args); @@ -12944,6 +13968,7 @@ explicit stack(const Container&); explicit stack(Container&&); template stack(InputIterator first, InputIterator last); + template<@\exposconcept{container-compatible-range}@ R> stack(from_range_t, R&& rg); template explicit stack(const Alloc&); template stack(const Container&, const Alloc&); template stack(Container&&, const Alloc&); @@ -12951,6 +13976,8 @@ template stack(stack&&, const Alloc&); template stack(InputIterator first, InputIterator last, const Alloc&); + template<@\exposconcept{container-compatible-range}@ R, class Alloc> + stack(from_range_t, R&& rg, const Alloc&); [[nodiscard]] bool empty() const { return c.empty(); } size_type size() const { return c.size(); } @@ -12958,6 +13985,8 @@ const_reference top() const { return c.back(); } void push(const value_type& x) { c.push_back(x); } void push(value_type&& x) { c.push_back(std::move(x)); } + template<@\exposconcept{container-compatible-range}@ R> + void push_range(R&& rg); template decltype(auto) emplace(Args&&... args) { return c.emplace_back(std::forward(args)...); } @@ -12972,6 +14001,9 @@ template stack(InputIterator, InputIterator) -> stack<@\exposid{iter-value-type}@>; + template + stack(from_range_t, R&&) -> stack>; + template stack(Container, Allocator) -> stack; @@ -12980,6 +14012,10 @@ -> stack<@\exposid{iter-value-type}@, deque<@\exposid{iter-value-type}@, Allocator>>; + template + stack(from_range_t, R&&, Allocator) + -> stack, deque, Allocator>>; + template struct uses_allocator, Alloc> : uses_allocator::type { }; @@ -13023,6 +14059,18 @@ \tcode{first} as the first argument and \tcode{last} as the second argument. \end{itemdescr} +\indexlibraryctor{stack}% +\begin{itemdecl} +template<@\exposconcept{container-compatible-range}@ R> + stack(from_range_t, R&& rg); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \tcode{c} with \tcode{ranges::to(std::forward(rg))}. +\end{itemdescr} + \rSec3[stack.cons.alloc]{Constructors with allocators} \pnum @@ -13103,6 +14151,35 @@ \tcode{alloc} as the third argument. \end{itemdescr} +\indexlibraryctor{stack}% +\begin{itemdecl} +template<@\exposconcept{container-compatible-range}@ R, class Alloc> + stack(from_range_t, R&& rg, const Alloc& a); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes +\tcode{c} with \tcode{ranges::to(std::forward(rg), a)}. +\end{itemdescr} + +\rSec3[stack.mod]{Modifiers} + +\indexlibrarymember{push_range}{stack}% +\begin{itemdecl} +template<@\exposconcept{container-compatible-range}@ R> + void push_range(R&& rg); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to \tcode{c.append_range(std::forward(rg))} +if that is a valid expression, +otherwise \tcode{ranges::copy(rg, back_inserter(c))}. +\end{itemdescr} + \rSec3[stack.ops]{Operators} \indexlibrarymember{operator==}{stack}% diff --git a/source/ranges.tex b/source/ranges.tex index 3121b25f21..7e0ebb1bd0 100644 --- a/source/ranges.tex +++ b/source/ranges.tex @@ -139,6 +139,16 @@ template<@\libconcept{range}@ R> using borrowed_subrange_t = @\seebelow@; + // \ref{range.utility.conv}, range conversions + template requires (!@\libconcept{view}@) + constexpr C to(R&& r, Args&&... args); + template class C, @\libconcept{input_range}@ R, class... Args> + constexpr auto to(R&& r, Args&&... args) -> @\seebelow@; + template requires (!@\libconcept{view}@) + constexpr auto to(Args&&... args) -> @\seebelow@; + template class C, class... Args> + constexpr auto to(Args&&... args) -> @\seebelow@; + // \ref{range.empty}, empty view template requires is_object_v @@ -402,6 +412,9 @@ struct tuple_element<1, const ranges::subrange> { using type = S; }; + + struct from_range_t { explicit from_range_t() = default; }; + inline constexpr from_range_t from_range{}; } \end{codeblock} @@ -1987,6 +2000,221 @@ denote \tcode{dangling}. \end{itemize} +\rSec2[range.utility.conv]{Range conversions} + +\rSec3[range.utility.conv.general]{General} + +\pnum +The range conversion functions construct +an object (usually a container) from a range, +by using a constructor taking a range, +a \tcode{from_range_t} tagged constructor, or +a constructor taking a pair of iterators, or +by inserting each element of the range into the default-constructed object. + +\pnum +\tcode{ranges::to} is applied recursively, +allowing the conversion of a range of ranges. + +\begin{example} +\begin{codeblock} +string_view str = "the quick brown fox"; +auto words = views::split(str, ' ') | to>(); +// \tcode{words} is \tcode{vector\{"the", "quick", "brown", "fox"\}} +\end{codeblock} +\end{example} + +\pnum +Let \exposid{reservable-container} be defined as follows: +\begin{codeblock} +template +constexpr bool @\exposid{reservable-container}@ = // \expos + @\libconcept{sized_range}@ && + requires(Container& c, range_size_t n) { + c.reserve(n); + { c.capacity() } -> @\libconcept{same_as}@; + { c.max_size() } -> @\libconcept{same_as}@; + }; +\end{codeblock} + +\pnum +Let \exposid{container-insertable} be defined as follows: +\begin{codeblock} +template +constexpr bool @\exposid{container-insertable}@ = // \expos + requires(Container& c, Ref&& ref) { + requires (requires { c.push_back(std::forward(ref)); } || + requires { c.insert(c.end(), std::forward(ref)); }); + }; +\end{codeblock} + +\pnum +Let \exposid{container-inserter} be defined as follows: +\begin{codeblock} +template +auto @\exposid{container-inserter}@(C& c) { // \expos + if constexpr (requires { c.push_back(declval()); }) + return back_inserter(c); + else + return inserter(c, c.end()); +}; +\end{codeblock} + +\rSec3[range.utility.conv.to]{\tcode{ranges::to}} + +\indexlibrarymember{to}{ranges}% +\begin{itemdecl} +template requires (!@\libconcept{view}@) + constexpr C to(R&& r, Args&&... args); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +An object of type \tcode{C} +constructed from the elements of \tcode{r} in the following manner: +\begin{itemize} +\item +If \tcode{\libconcept{convertible_to}, range_value_t>} +is \tcode{true}: +\begin{itemize} +\item +If \tcode{\libconcept{constructible_from}} is \tcode{true}: +\begin{codeblock} +C(std::forward(r), std::forward(args)...) +\end{codeblock} +\item +Otherwise, if +\tcode{\libconcept{constructible_from}} +is \tcode{true}: +\begin{codeblock} +C(from_range, std::forward(r), std::forward(args)...) +\end{codeblock} +\item +Otherwise, if +\begin{itemize} +\item +\tcode{\libconcept{common_range}} is \tcode{true}, +\item +\tcode{\exposconcept{cpp17-input-iterator}>} is \tcode{true}, and +\item +\tcode{\libconcept{constructible_from}, sentinel_t, Args...>} +is \tcode{true}: +\end{itemize} +\begin{codeblock} +C(ranges::begin(r), ranges::end(r), std::forward(args)...) +\end{codeblock} +\item +Otherwise, if +\begin{itemize} +\item +\tcode{\libconcept{constructible_from}} is \tcode{true}, and +\item +\tcode{\exposid{container-insertable}>} is \tcode{true}: +\end{itemize} +\begin{codeblock} +C c(std::forward(args)...); +if constexpr (@\libconcept{sized_range}@ && @\exposid{reservable-container}@) + c.reserve(ranges::size(r)); +ranges::copy(r, @\exposid{container-inserter}@>(c)); +\end{codeblock} +\end{itemize} + +\item +Otherwise, +if \tcode{\libconcept{input_range}>} is \tcode{true}: +\begin{codeblock} +to(r | views::transform([](auto&& elem) { + return to>(std::forward(elem)); +}), std::forward(args)...); +\end{codeblock} + +\item +Otherwise, the program is ill-formed. +\end{itemize} +\end{itemdescr} + +\indexlibrarymember{to}{ranges}% +\begin{itemdecl} +template class C, @\libconcept{input_range}@ R, class... Args> + constexpr auto to(R&& r, Args&&... args); +\end{itemdecl} + +\begin{itemdescr} +\pnum +Let \exposid{input-iterator} be an exposition-only type: +\begin{codeblock} +struct @\exposid{input-iterator}@ { // \expos + using iterator_category = input_iterator_tag; + using value_type = range_value_t; + using difference_type = ptrdiff_t; + using pointer = add_pointer_t>; + using reference = range_reference_t; + reference operator*() const; + pointer operator->() const; + @\exposid{input-iterator}@& operator++(); + @\exposid{input-iterator}@ operator++(int); + bool operator==(const @\exposid{input-iterator}@&) const; +}; +\end{codeblock} +\begin{note} +\exposid{input-iterator} meets +the syntactic requirements of \oldconcept{InputIterator}. +\end{note} + +\pnum +Let \tcode{\placeholder{DEDUCE_EXPR}} be defined as follows: +\begin{itemize} +\item +\tcode{C(declval(), declval()...)} if that is a valid expression, +\item +otherwise, \tcode{C(from_range, declval(), declval()...)} +if that is a valid expression, +\item +otherwise, +\begin{codeblock} +C(declval<@\exposid{input-iterator}@>(), declval<@\exposid{input-iterator}@>(), declval()...) +\end{codeblock} +if that is a valid expression, +\item +otherwise, the program is ill-formed. +\end{itemize} + +\pnum +\returns +\tcode{to(std::forward(r), std::forward(args)...)}. +\end{itemdescr} + +\rSec3[range.utility.conv.adaptors]{\tcode{ranges::to} adaptors} + +\indexlibrarymember{to}{ranges}% +\begin{itemdecl} +template requires (!@\libconcept{view}@) + constexpr auto to(Args&&... args); +template class C, class... Args> + constexpr auto to(Args&&... args); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\returns +A range adaptor closure object\iref{range.adaptor.object} \tcode{f} +that is a perfect forwarding call wrapper\iref{func.require} +with the following properties: +\begin{itemize} +\item +It has no target object. +\item +Its bound argument entities \tcode{bound_args} consist of +objects of types \tcode{decay_t...} +direct-non-list-initialized with \tcode{std::forward(args)...}, +respectively. +\item +Its call pattern is \tcode{to(r, bound_args...)}, +where \tcode{r} is the argument used in a function call expression of \tcode{f}. +\end{itemize} +\end{itemdescr} + \rSec1[range.factories]{Range factories} \rSec2[range.factories.general]{General} diff --git a/source/strings.tex b/source/strings.tex index 7400a02ff0..ef41984dde 100644 --- a/source/strings.tex +++ b/source/strings.tex @@ -831,6 +831,8 @@ template constexpr basic_string(InputIterator begin, InputIterator end, const Allocator& a = Allocator()); + template<@\exposconcept{container-compatible-range}@ R> + constexpr basic_string(from_range_t, R&& rg, const Allocator& a = Allocator()); constexpr basic_string(initializer_list, const Allocator& = Allocator()); constexpr basic_string(const basic_string&, const Allocator&); constexpr basic_string(basic_string&&, const Allocator&); @@ -905,6 +907,8 @@ constexpr basic_string& append(size_type n, charT c); template constexpr basic_string& append(InputIterator first, InputIterator last); + template<@\exposconcept{container-compatible-range}@ R> + constexpr basic_string& append_range(R&& rg); constexpr basic_string& append(initializer_list); constexpr void push_back(charT c); @@ -923,6 +927,8 @@ constexpr basic_string& assign(size_type n, charT c); template constexpr basic_string& assign(InputIterator first, InputIterator last); + template<@\exposconcept{container-compatible-range}@ R> + constexpr basic_string& assign_range(R&& rg); constexpr basic_string& assign(initializer_list); constexpr basic_string& insert(size_type pos, const basic_string& str); @@ -940,6 +946,8 @@ constexpr iterator insert(const_iterator p, size_type n, charT c); template constexpr iterator insert(const_iterator p, InputIterator first, InputIterator last); + template<@\exposconcept{container-compatible-range}@ R> + constexpr iterator insert_range(const_iterator p, R&& rg); constexpr iterator insert(const_iterator p, initializer_list); constexpr basic_string& erase(size_type pos = 0, size_type n = npos); @@ -970,6 +978,8 @@ template constexpr basic_string& replace(const_iterator i1, const_iterator i2, InputIterator j1, InputIterator j2); + template<@\exposconcept{container-compatible-range}@ R> + constexpr basic_string& replace_with_range(const_iterator i1, const_iterator i2, R&& rg); constexpr basic_string& replace(const_iterator, const_iterator, initializer_list); constexpr size_type copy(charT* s, size_type n, size_type pos = 0) const; @@ -1066,6 +1076,12 @@ char_traits::value_type>, Allocator>; + template>> + basic_string(from_range_t, R&&, Allocator = Allocator()) + -> basic_string, char_traits>, + Allocator>; + template> @@ -1324,6 +1340,19 @@ as specified in \ref{sequence.reqmts}. \end{itemdescr} +\indexlibraryctor{basic_string}% +\begin{itemdecl} +template<@\exposconcept{container-compatible-range}@ R> + constexpr basic_string(from_range_t, R&& rg, const Allocator& = Allocator()); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Constructs a string from the values in the range \tcode{rg}, +as specified in \ref{sequence.reqmts}. +\end{itemdescr} + \indexlibraryctor{basic_string}% \begin{itemdecl} constexpr basic_string(initializer_list il, const Allocator& a = Allocator()); @@ -2076,6 +2105,18 @@ Equivalent to: \tcode{return append(basic_string(first, last, get_allocator()));} \end{itemdescr} +\indexlibrarymember{append_range}{basic_string}% +\begin{itemdecl} +template<@\exposconcept{container-compatible-range}@ R> + constexpr basic_string& append_range(R&& rg); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return append(basic_string(from_range, std::forward(rg), get_allocator()));} +\end{itemdescr} + \indexlibrarymember{append}{basic_string}% \begin{itemdecl} constexpr basic_string& append(initializer_list il); @@ -2269,6 +2310,18 @@ Equivalent to: \tcode{return assign(basic_string(first, last, get_allocator()));} \end{itemdescr} +\indexlibrarymember{assign_range}{basic_string}% +\begin{itemdecl} +template<@\exposconcept{container-compatible-range}@ R> + constexpr basic_string& assign_range(R&& rg); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return assign(basic_string(from_range, std::forward(rg), get_allocator()));} +\end{itemdescr} + \rSec4[string.insert]{\tcode{basic_string::insert}} \indexlibrarymember{insert}{basic_string}% @@ -2486,6 +2539,28 @@ \tcode{p} if \tcode{first == last}. \end{itemdescr} +\indexlibrarymember{insert_range}{basic_string}% +\begin{itemdecl} +template<@\exposconcept{container-compatible-range}@ R> + constexpr iterator insert_range(const_iterator p, R&& rg); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{p} is a valid iterator on \tcode{*this}. + +\pnum +\effects +Equivalent to +\tcode{insert(p - begin(), basic_string(from_range, std::forward(rg), get_allocator()))}. + +\pnum +\returns +An iterator which refers to the first inserted character, or +\tcode{p} if \tcode{rg} is empty. +\end{itemdescr} + \indexlibrarymember{insert}{basic_string}% \begin{itemdecl} constexpr iterator insert(const_iterator p, initializer_list il); @@ -2851,6 +2926,21 @@ Equivalent to: \tcode{return replace(i1, i2, basic_string(j1, j2, get_allocator()));} \end{itemdescr} +\indexlibrarymember{replace_with_range}{basic_string}% +\begin{itemdecl} +template<@\exposconcept{container-compatible-range}@ R> + constexpr basic_string& replace_with_range(const_iterator i1, const_iterator i2, R&& rg); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +return replace(i1, i2, basic_string(from_range, std::forward(rg), get_allocator())); +\end{codeblock} +\end{itemdescr} + \indexlibrarymember{replace}{basic_string}% \begin{itemdecl} constexpr basic_string& replace(const_iterator i1, const_iterator i2, initializer_list il); diff --git a/source/support.tex b/source/support.tex index a25fd74be2..9e116d660a 100644 --- a/source/support.tex +++ b/source/support.tex @@ -602,6 +602,9 @@ #define @\defnlibxname{cpp_lib_constexpr_typeinfo}@ 202106L // also in \libheader{typeinfo} #define @\defnlibxname{cpp_lib_constexpr_utility}@ 201811L // also in \libheader{utility} #define @\defnlibxname{cpp_lib_constexpr_vector}@ 201907L // also in \libheader{vector} +#define @\defnlibxname{cpp_lib_containers_ranges}@ 202202L + // also in \libheader{vector}, \libheader{list}, \libheader{forward_list}, \libheader{map}, \libheader{set}, \libheader{unordered_map}, \libheader{unordered_set}, + // \libheader{deque}, \libheader{queue}, \libheader{priority_queue}, \libheader{stack}, \libheader{string} #define @\defnlibxname{cpp_lib_coroutine}@ 201902L // also in \libheader{coroutine} #define @\defnlibxname{cpp_lib_destroying_delete}@ 201806L // also in \libheader{new} #define @\defnlibxname{cpp_lib_enable_shared_from_this}@ 201603L // also in \libheader{memory} @@ -668,6 +671,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_to_container}@ 202202L // also in \libheader{ranges} #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}