diff --git a/source/ranges.tex b/source/ranges.tex index f1b9593841..4e91f4a61e 100644 --- a/source/ranges.tex +++ b/source/ranges.tex @@ -194,6 +194,14 @@ template inline constexpr bool enable_borrowed_range> = true; + // \ref{range.owning.view}, owning view + template + requires @\seebelow@ + class owning_view; + + template + inline constexpr bool enable_borrowed_range> = enable_borrowed_range; + // \ref{range.filter}, filter view template<@\libconcept{input_range}@ V, @\libconcept{indirect_unary_predicate}@> Pred> requires @\libconcept{view}@ && is_object_v @@ -1176,9 +1184,9 @@ \pnum The \libconcept{view} concept specifies the requirements of a \libconcept{range} type -that has constant time move construction, move assignment, and destruction; -that is, the cost of these operations is -independent of the number of elements in the \libconcept{view}. +that has the semantic properties below, +which make it suitable for use in +constructing range adaptor pipelines\iref{range.adaptors}. \begin{itemdecl} template @@ -1194,10 +1202,17 @@ \tcode{T} has \bigoh{1} move construction; and \item -\tcode{T} has \bigoh{1} move assignment; and +move assignment of an object of type \tcode{T} +is no more complex than destruction followed by move construction; and \item -\tcode{T} has \bigoh{1} destruction; and +if $N$ copies and/or moves are made from an object of type \tcode{T} +that contained $M$ elements, +then those $N$ objects have \bigoh{N+M} destruction +\begin{note} +This implies that a moved-from object of type \tcode{T} has \bigoh{1} destruction +\end{note}% +; and \item \tcode{\libconcept{copy_constructible}} is \tcode{false}, or @@ -1205,7 +1220,8 @@ \item \tcode{\libconcept{copyable}} is \tcode{false}, or -\tcode{T} has \bigoh{1} copy assignment. +copy assignment of an object of type \tcode{T} +is no more complex than destruction followed by copy construction. \end{itemize} \pnum @@ -1220,8 +1236,9 @@ \item A \libconcept{range} type that generates its elements on demand. \end{itemize} -Most containers\iref{containers} are not views since -destruction of the container destroys the elements, +A container such as \tcode{vector} +does not meet the semantic requirements of \libconcept{view} +since copying the container copies all of the elements, which cannot be done in constant time. \end{example} \end{itemdescr} @@ -1325,6 +1342,18 @@ @\libconcept{range}@ && @\libconcept{same_as}@, sentinel_t>; \end{itemdecl} +\begin{itemdecl} +template + inline constexpr bool @\exposidnc{is-initializer-list}@ = @\seebelow@; // \expos +\end{itemdecl} + +\begin{itemdescr} +\pnum +For a type \tcode{R}, +\tcode{\exposid{is-initializer-list}} is \tcode{true} if and only if +\tcode{remove_cvref_t} is a specialization of \tcode{initializer_list}. +\end{itemdescr} + \pnum The \libconcept{viewable_range} concept specifies the requirements of a \libconcept{range} type that can be converted to a \libconcept{view} safely. @@ -1334,7 +1363,8 @@ concept @\deflibconcept{viewable_range}@ = @\libconcept{range}@ && ((@\libconcept{view}@> && @\libconcept{constructible_from}@, T>) || - (!@\libconcept{view}@> && @\libconcept{borrowed_range}@)); + (!@\libconcept{view}@> && + (is_lvalue_reference_v || (@\libconcept{movable}@> && !@\exposid{is-initializer-list}@)))); \end{itemdecl} \rSec1[range.utility]{Range utilities} @@ -3280,7 +3310,7 @@ \item Otherwise, \tcode{ref_view\{E\}} if that expression is well-formed. -\item Otherwise, \tcode{subrange\{E\}}. +\item Otherwise, \tcode{owning_view\{E\}}. \end{itemize} \rSec3[range.ref.view]{Class template \tcode{ref_view}} @@ -3346,6 +3376,67 @@ \end{codeblock} \end{itemdescr} +\rSec3[range.owning.view]{Class template \tcode{owning_view}} + +\pnum +\tcode{owning_view} is a move-only view +of the elements of some other \libconcept{range}. +\begin{codeblock} +namespace std::ranges { + template<@\libconcept{range}@ R> + requires @\libconcept{movable}@ && (!@\exposid{is-initializer-list}@) // see \ref{range.refinements} + class owning_view : public view_interface> { + private: + R @\exposid{r_}@ = R(); // \expos + public: + owning_view() requires @\libconcept{default_initializable}@ = default; + constexpr owning_view(R&& t); + + owning_view(owning_view&&) = default; + owning_view& operator=(owning_view&&) = default; + + constexpr R& base() & noexcept { return @\exposid{r_}@; } + constexpr const R& base() const& noexcept { return @\exposid{r_}@; } + constexpr R&& base() && noexcept { return std::move(@\exposid{r_}@); } + constexpr const R&& base() const&& noexcept { return std::move(@\exposid{r_}@); } + + constexpr iterator_t begin() { return ranges::begin(@\exposid{r_}@); } + constexpr sentinel_t end() { return ranges::end(@\exposid{r_}@); } + + constexpr auto begin() const requires @\libconcept{range}@ + { return ranges::begin(@\exposid{r_}@); } + constexpr auto end() const requires @\libconcept{range}@ + { return ranges::end(@\exposid{r_}@); } + + constexpr bool empty() + requires requires { ranges::empty(@\exposid{r_}@); } + { return ranges::empty(@\exposid{r_}@); } + constexpr bool empty() const + requires requires { ranges::empty(@\exposid{r_}@); } + { return ranges::empty(@\exposid{r_}@); } + + constexpr auto size() requires @\libconcept{sized_range}@ + { return ranges::size(@\exposid{r_}@); } + constexpr auto size() const requires @\libconcept{sized_range}@ + { return ranges::size(@\exposid{r_}@); } + + constexpr auto data() requires @\libconcept{contiguous_range}@ + { return ranges::data(@\exposid{r_}@); } + constexpr auto data() const requires @\libconcept{contiguous_range}@ + { return ranges::data(@\exposid{r_}@); } + }; +} +\end{codeblock} + +\begin{itemdecl} +constexpr owning_view(R&& t); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \exposid{r_} with \tcode{std::move(t)}. +\end{itemdescr} \rSec2[range.filter]{Filter view} diff --git a/source/support.tex b/source/support.tex index 1ace3eba2a..a960392849 100644 --- a/source/support.tex +++ b/source/support.tex @@ -660,7 +660,7 @@ #define @\defnlibxname{cpp_lib_parallel_algorithm}@ 201603L // also in \libheader{algorithm}, \libheader{numeric} #define @\defnlibxname{cpp_lib_polymorphic_allocator}@ 201902L // also in \libheader{memory_resource} #define @\defnlibxname{cpp_lib_quoted_string_io}@ 201304L // also in \libheader{iomanip} -#define @\defnlibxname{cpp_lib_ranges}@ 202106L +#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_raw_memory_algorithms}@ 201606L // also in \libheader{memory}