diff --git a/source/ranges.tex b/source/ranges.tex index 58f2ef0c01..35c9e48116 100644 --- a/source/ranges.tex +++ b/source/ranges.tex @@ -4796,10 +4796,10 @@ @\exposidnc{movable-box}@ @\exposid{pred_}@; // \expos // \ref{range.filter.iterator}, class \tcode{filter_view::\exposid{iterator}} - class @\exposid{iterator}@; // \expos + template class @\exposid{iterator}@; // \expos // \ref{range.filter.sentinel}, class \tcode{filter_view::\exposid{sentinel}} - class @\exposid{sentinel}@; // \expos + template class @\exposid{sentinel}@; // \expos public: filter_view() requires @\libconcept{default_initializable}@ && @\libconcept{default_initializable}@ = default; @@ -4810,12 +4810,21 @@ constexpr const Pred& pred() const; - constexpr @\exposid{iterator}@ begin(); + constexpr @\exposid{iterator}@ begin(); + constexpr @\exposid{iterator}@ begin() const + requires (@\libconcept{input_range}@ && !@\libconcept{forward_range}@ && + @\libconcept{indirect_unary_predicate}@>); + constexpr auto end() { if constexpr (@\libconcept{common_range}@) - return @\exposid{iterator}@{*this, ranges::end(@\exposid{base_}@)}; + return @\exposid{iterator}@{*this, ranges::end(@\exposid{base_}@)}; else - return @\exposid{sentinel}@{*this}; + return @\exposid{sentinel}@{*this}; + } + constexpr @\exposid{sentinel}@ end() const + requires (@\libconcept{input_range}@ && !@\libconcept{forward_range}@ && + @\libconcept{indirect_unary_predicate}@>) { + return @\exposid{sentinel}@{*this}; } }; @@ -4849,7 +4858,7 @@ \indexlibrarymember{begin}{filter_view}% \begin{itemdecl} -constexpr @\exposid{iterator}@ begin(); +constexpr @\exposid{iterator}@ begin(); \end{itemdecl} \begin{itemdescr} @@ -4870,7 +4879,27 @@ \tcode{filter_view} for use on subsequent calls. \end{itemdescr} -\rSec3[range.filter.iterator]{Class \tcode{filter_view::\exposid{iterator}}} +\indexlibrarymember{begin}{filter_view}% +\begin{itemdecl} +constexpr @\exposid{iterator}@ begin() const + requires (@\libconcept{input_range}@ && !@\libconcept{forward_range}@ && + @\libconcept{indirect_unary_predicate}@>); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\expects +\tcode{\exposid{pred_}.has_value()} is \tcode{true}. + +\pnum +\returns +\tcode{\{*this, ranges::find_if(\exposid{base_}, ref(*\exposid{pred_}))\}}. +\begin{note} +This function does not cache the result within the \tcode{filter_view}. +\end{note} +\end{itemdescr} + +\rSec3[range.filter.iterator]{Class template \tcode{filter_view::\exposid{iterator}}} \indexlibraryglobal{filter_view::\exposid{iterator}}% \indexlibrarymember{iterator}{filter_view}% @@ -4878,55 +4907,67 @@ namespace std::ranges { template<@\libconcept{input_range}@ V, @\libconcept{indirect_unary_predicate}@> Pred> requires @\libconcept{view}@ && is_object_v + template class filter_view::@\exposid{iterator}@ { private: - iterator_t @\exposid{current_}@ = iterator_t(); // \expos - filter_view* @\exposid{parent_}@ = nullptr; // \expos + using @\exposid{Parent}@ = @\exposid{maybe-const}@; // \expos + using @\exposid{Base}@ = @\exposid{maybe-const}@; // \expos + iterator_t @\exposid{current_}@ = iterator_t(); // \expos + @\exposid{Parent}@* @\exposid{parent_}@ = nullptr; // \expos public: using iterator_concept = @\seebelownc@; using iterator_category = @\seebelownc@; // not always present - using value_type = range_value_t; - using difference_type = range_difference_t; + using value_type = range_value_t; + using difference_type = range_difference_t; - @\exposid{iterator}@() requires @\libconcept{default_initializable}@> = default; - constexpr @\exposid{iterator}@(filter_view& parent, iterator_t current); + @\exposid{iterator}@() requires @\libconcept{default_initializable}@> = default; + constexpr @\exposid{iterator}@(@\exposid{Parent}@& parent, iterator_t current); + constexpr @\exposid{iterator}@(iterator i) + requires Const && @\libconcept{convertible_to}@, iterator_t>; - constexpr const iterator_t& base() const & noexcept; - constexpr iterator_t base() &&; - constexpr range_reference_t operator*() const; - constexpr iterator_t operator->() const - requires @\exposconcept{has-arrow}@> && @\libconcept{copyable}@>; + constexpr const iterator_t& base() const & noexcept; + constexpr iterator_t base() &&; + constexpr range_reference_t operator*() const; + constexpr iterator_t operator->() const + requires @\exposconcept{has-arrow}@> && @\libconcept{copyable}@>; constexpr @\exposid{iterator}@& operator++(); constexpr void operator++(int); - constexpr @\exposid{iterator}@ operator++(int) requires @\libconcept{forward_range}@; + constexpr @\exposid{iterator}@ operator++(int) requires @\libconcept{forward_range}@; - constexpr @\exposid{iterator}@& operator--() requires @\libconcept{bidirectional_range}@; - constexpr @\exposid{iterator}@ operator--(int) requires @\libconcept{bidirectional_range}@; + constexpr @\exposid{iterator}@& operator--() requires @\libconcept{bidirectional_range}@; + constexpr @\exposid{iterator}@ operator--(int) requires @\libconcept{bidirectional_range}@; friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) - requires @\libconcept{equality_comparable}@>; + requires @\libconcept{equality_comparable}@>; - friend constexpr range_rvalue_reference_t iter_move(const @\exposid{iterator}@& i) + friend constexpr range_rvalue_reference_t iter_move(const @\exposid{iterator}@& i) noexcept(noexcept(ranges::iter_move(i.@\exposid{current_}@))); friend constexpr void iter_swap(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) noexcept(noexcept(ranges::iter_swap(x.@\exposid{current_}@, y.@\exposid{current_}@))) - requires @\libconcept{indirectly_swappable}@>; + requires @\libconcept{indirectly_swappable}@>; }; } \end{codeblock} \pnum -Modification of the element a \tcode{filter_view::\exposid{iterator}} denotes is -permitted, but results in undefined behavior if the resulting value does not -satisfy the filter predicate. +\begin{note} +Modification of the element a \tcode{filter_view::\exposid{iterator}} denotes +can result in undefined behavior +if the underlying range is a \libconcept{forward_range} and +the resulting value does not satisfy the filter predicate +when the predicate is next evaluated for that element\iref{concepts.equality}. +\end{note} \pnum \tcode{\exposid{iterator}::iterator_concept} is defined as follows: \begin{itemize} -\item If \tcode{V} models \libconcept{bidirectional_range}, then +\item If \tcode{Const} is \tcode{true}, +then \tcode{iterator_concept} denotes \tcode{input_iterator_tag}. + +\item Otherwise, if \tcode{V} models \libconcept{bidirectional_range}, then \tcode{iterator_concept} denotes \tcode{bidirectional_iterator_tag}. \item Otherwise, if \tcode{V} models \libconcept{forward_range}, then @@ -4937,12 +4978,12 @@ \pnum The member \grammarterm{typedef-name} \tcode{iterator_category} is declared -if and only if \tcode{V} models \libconcept{forward_range}. +if and only if \tcode{Base} models \libconcept{forward_range}. In that case, \tcode{\exposid{iterator}::iterator_category} is defined as follows: \begin{itemize} \item Let \tcode{C} denote the type -\tcode{iterator_traits>::iterator_category}. +\tcode{iterator_traits>::iterator_category}. \item If \tcode{C} models \tcode{\libconcept{derived_from}}, @@ -4957,7 +4998,7 @@ \indexlibraryctor{filter_view::\exposid{iterator}}% \begin{itemdecl} -constexpr @\exposid{iterator}@(filter_view& parent, iterator_t current); +constexpr @\exposid{iterator}@(@\exposid{Parent}@& parent, iterator_t current); \end{itemdecl} \begin{itemdescr} @@ -4967,9 +5008,22 @@ \exposid{parent_} with \tcode{addressof(parent)}. \end{itemdescr} +\indexlibraryctor{filter_view::\exposid{iterator}}% +\begin{itemdecl} +constexpr @\exposid{iterator}@(@\exposid{iterator}@ i) + requires Const && @\libconcept{convertible_to}@, iterator_t>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \exposid{parent_} with \tcode{i.\exposid{parent_}} and +\exposid{current_} with \tcode{std::move(i.\exposid{current_})}. +\end{itemdescr} + \indexlibrarymember{base}{filter_view::\exposid{iterator}}% \begin{itemdecl} -constexpr const iterator_t& base() const & noexcept; +constexpr const iterator_t& base() const & noexcept; \end{itemdecl} \begin{itemdescr} @@ -4980,7 +5034,7 @@ \indexlibrarymember{base}{filter_view::\exposid{iterator}}% \begin{itemdecl} -constexpr iterator_t base() &&; +constexpr iterator_t base() &&; \end{itemdecl} \begin{itemdescr} @@ -4991,7 +5045,7 @@ \indexlibrarymember{operator*}{filter_view::\exposid{iterator}}% \begin{itemdecl} -constexpr range_reference_t operator*() const; +constexpr range_reference_t operator*() const; \end{itemdecl} \begin{itemdescr} @@ -5002,8 +5056,8 @@ \indexlibrarymember{operator->}{filter_view::\exposid{iterator}}% \begin{itemdecl} -constexpr iterator_t operator->() const - requires @\exposconcept{has-arrow}@> && @\libconcept{copyable}@>; +constexpr iterator_t operator->() const + requires @\exposconcept{has-arrow}@> && @\libconcept{copyable}@>; \end{itemdecl} \begin{itemdescr} @@ -5041,7 +5095,7 @@ \indexlibrarymember{operator++}{filter_view::\exposid{iterator}}% \begin{itemdecl} -constexpr @\exposid{iterator}@ operator++(int) requires @\libconcept{forward_range}@; +constexpr @\exposid{iterator}@ operator++(int) requires @\libconcept{forward_range}@; \end{itemdecl} \begin{itemdescr} @@ -5057,7 +5111,7 @@ \indexlibrarymember{operator--}{filter_view::\exposid{iterator}}% \begin{itemdecl} -constexpr @\exposid{iterator}@& operator--() requires @\libconcept{bidirectional_range}@; +constexpr @\exposid{iterator}@& operator--() requires @\libconcept{bidirectional_range}@; \end{itemdecl} \begin{itemdescr} @@ -5074,7 +5128,7 @@ \indexlibrarymember{operator--}{filter_view::\exposid{iterator}}% \begin{itemdecl} -constexpr @\exposid{iterator}@ operator--(int) requires @\libconcept{bidirectional_range}@; +constexpr @\exposid{iterator}@ operator--(int) requires @\libconcept{bidirectional_range}@; \end{itemdecl} \begin{itemdescr} @@ -5091,7 +5145,7 @@ \indexlibrarymember{operator==}{filter_view::\exposid{iterator}}% \begin{itemdecl} friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) - requires @\libconcept{equality_comparable}@>; + requires @\libconcept{equality_comparable}@>; \end{itemdecl} \begin{itemdescr} @@ -5102,7 +5156,7 @@ \indexlibrarymember{iter_move}{filter_view::\exposid{iterator}}% \begin{itemdecl} -friend constexpr range_rvalue_reference_t iter_move(const @\exposid{iterator}@& i) +friend constexpr range_rvalue_reference_t iter_move(const @\exposid{iterator}@& i) noexcept(noexcept(ranges::iter_move(i.@\exposid{current_}@))); \end{itemdecl} @@ -5116,7 +5170,7 @@ \begin{itemdecl} friend constexpr void iter_swap(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) noexcept(noexcept(ranges::iter_swap(x.@\exposid{current_}@, y.@\exposid{current_}@))) - requires @\libconcept{indirectly_swappable}@>; + requires @\libconcept{indirectly_swappable}@>; \end{itemdecl} \begin{itemdescr} @@ -5125,7 +5179,7 @@ Equivalent to \tcode{ranges::iter_swap(x.\exposid{current_}, y.\exposid{current_})}. \end{itemdescr} -\rSec3[range.filter.sentinel]{Class \tcode{filter_view::\exposid{sentinel}}} +\rSec3[range.filter.sentinel]{Class template \tcode{filter_view::\exposid{sentinel}}} \indexlibraryglobal{filter_view::\exposid{sentinel}}% \indexlibrarymember{sentinel}{filter_view}% @@ -5133,24 +5187,42 @@ namespace std::ranges { template<@\libconcept{input_range}@ V, @\libconcept{indirect_unary_predicate}@> Pred> requires @\libconcept{view}@ && is_object_v + template class filter_view::@\exposid{sentinel}@ { private: - sentinel_t @\exposid{end_}@ = sentinel_t(); // \expos + using @\exposid{Base}@ = @\exposid{maybe-const}@; // \expos + sentinel_t @\exposid{end_}@ = sentinel_t(); // \expos public: @\exposid{sentinel}@() = default; - constexpr explicit @\exposid{sentinel}@(filter_view& parent); + constexpr @\exposid{sentinel}@(@\exposid{sentinel}@ other) + requires Const && @\libconcept{convertible_to}@, sentinel_t> + constexpr explicit @\exposid{sentinel}@(@\exposid{Parent}@& parent); - constexpr sentinel_t base() const; + constexpr sentinel_t base() const; - friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); + template + requires @\libconcept{sentinel_for}@, iterator_t<@\exposid{maybe-const}@>> + friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); }; } \end{codeblock} \indexlibraryctor{filter_view::\exposid{sentinel}}% \begin{itemdecl} -constexpr explicit @\exposid{sentinel}@(filter_view& parent); +constexpr @\exposid{sentinel}@(@\exposid{sentinel}@ other) + requires Const && @\libconcept{convertible_to}@, sentinel_t>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \exposid{end_} with \tcode{std::move(other.\exposid{end_})}. +\end{itemdescr} + +\indexlibraryctor{filter_view::\exposid{sentinel}}% +\begin{itemdecl} +constexpr explicit @\exposid{sentinel}@(@\exposid{Parent}@& parent); \end{itemdecl} \begin{itemdescr} @@ -5161,7 +5233,7 @@ \indexlibrarymember{base}{filter_view::\exposid{sentinel}}% \begin{itemdecl} -constexpr sentinel_t base() const; +constexpr sentinel_t base() const; \end{itemdecl} \begin{itemdescr} @@ -5172,7 +5244,9 @@ \indexlibrarymember{operator==}{filter_view::\exposid{sentinel}}% \begin{itemdecl} -friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); +template + requires @\libconcept{sentinel_for}@, iterator_t<@\exposid{maybe-const}@ >> + friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); \end{itemdecl} \begin{itemdescr} diff --git a/source/support.tex b/source/support.tex index 203a1bf45f..8d127ce457 100644 --- a/source/support.tex +++ b/source/support.tex @@ -797,6 +797,7 @@ #define @\defnlibxname{cpp_lib_ranges_concat}@ 202403L // freestanding, also in \libheader{ranges} #define @\defnlibxname{cpp_lib_ranges_contains}@ 202207L // freestanding, also in \libheader{algorithm} #define @\defnlibxname{cpp_lib_ranges_enumerate}@ 202302L // freestanding, also in \libheader{ranges} +#define @\defnlibxname{cpp_lib_ranges_filter}@ 202603L // freestanding, also in \libheader{ranges} #define @\defnlibxname{cpp_lib_ranges_find_last}@ 202207L // freestanding, also in \libheader{algorithm} #define @\defnlibxname{cpp_lib_ranges_fold}@ 202207L // freestanding, also in \libheader{algorithm} #define @\defnlibxname{cpp_lib_ranges_generate_random}@ 202403L // also in \libheader{random}