From c2dc9b05f8e1f821f53cca364a016ff0fc573eed Mon Sep 17 00:00:00 2001 From: Dawn Perchik Date: Wed, 24 Feb 2021 16:25:31 -0800 Subject: [PATCH 1/8] LWG3391 Problems with counted_iterator/move_iterator::base() const & --- source/iterators.tex | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/source/iterators.tex b/source/iterators.tex index b881fe12a2..f38f819f83 100644 --- a/source/iterators.tex +++ b/source/iterators.tex @@ -4096,7 +4096,7 @@ template constexpr move_iterator(const move_iterator& u); template constexpr move_iterator& operator=(const move_iterator& u); - constexpr iterator_type base() const &; + constexpr const iterator_type& base() const &; constexpr iterator_type base() &&; constexpr reference operator*() const; @@ -4226,18 +4226,10 @@ \indexlibrarymember{base}{move_iterator}% \begin{itemdecl} -constexpr Iterator base() const &; +constexpr const Iterator& base() const &; \end{itemdecl} \begin{itemdescr} -\pnum -\constraints -\tcode{Iterator} satisfies \libconcept{copy_constructible}. - -\pnum -\expects -\tcode{Iterator} models \libconcept{copy_constructible}. - \pnum \returns \tcode{current}. @@ -5170,7 +5162,7 @@ requires @\libconcept{assignable_from}@ constexpr counted_iterator& operator=(const counted_iterator& x); - constexpr I base() const & requires copy_constructible; + constexpr const I& base() const &; constexpr I base() &&; constexpr iter_difference_t count() const noexcept; constexpr decltype(auto) operator*(); @@ -5297,7 +5289,7 @@ \indexlibrarymember{base}{counted_iterator}% \begin{itemdecl} -constexpr I base() const & requires copy_constructible; +constexpr const I& base() const &; \end{itemdecl} \begin{itemdescr} From 8be9a47572d9fe6069e755f5c7f74b0898f3fdcc Mon Sep 17 00:00:00 2001 From: Dawn Perchik Date: Wed, 24 Feb 2021 16:35:29 -0800 Subject: [PATCH 2/8] LWG3433 subrange::advance(n) has UB when n < 0 --- source/ranges.tex | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/source/ranges.tex b/source/ranges.tex index 0d1103ac70..dd2b6ffadd 100644 --- a/source/ranges.tex +++ b/source/ranges.tex @@ -1765,22 +1765,21 @@ \pnum \effects Equivalent to: -\begin{itemize} -\item If \exposid{StoreSize} is \tcode{true}, \begin{codeblock} +if constexpr (bidirectional_iterator) { + if (n < 0) { + ranges::advance(@\exposid{begin_}@, n); + if constexpr (@\exposid{StoreSize}@) + @\exposid{size_}@ += @\placeholdernc{to-unsigned-like}@(-n); + return *this; + } +} + auto d = n - ranges::advance(@\exposid{begin_}@, n, @\exposid{end_}@); -if (d >= 0) +if constexpr (@\exposid{StoreSize}@) @\exposid{size_}@ -= @\placeholdernc{to-unsigned-like}@(d); -else - @\exposid{size_}@ += @\placeholdernc{to-unsigned-like}@(-d); return *this; \end{codeblock} -\item Otherwise, -\begin{codeblock} -ranges::advance(@\exposid{begin_}@, n, @\exposid{end_}@); -return *this; -\end{codeblock} -\end{itemize} \end{itemdescr} \indexlibrarymember{get}{subrange}% From 575978fc97701af95b1fd050a2f5a62ffe8c44b5 Mon Sep 17 00:00:00 2001 From: Dawn Perchik Date: Wed, 24 Feb 2021 16:38:48 -0800 Subject: [PATCH 3/8] LWG3490 ranges::drop_while_view::begin() is missing a precondition --- source/ranges.tex | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/source/ranges.tex b/source/ranges.tex index dd2b6ffadd..0cc3e32c4a 100644 --- a/source/ranges.tex +++ b/source/ranges.tex @@ -4913,6 +4913,10 @@ \end{itemdecl} \begin{itemdescr} +\pnum +\expects +\tcode{\exposid{pred_}.has_value()} is \tcode{true}. + \pnum \returns \tcode{ranges::find_if_not(\exposid{base_}, cref(*\exposid{pred_}))}. From 8e9f7523a0b558037acf108851cf617e599e3d0c Mon Sep 17 00:00:00 2001 From: Dawn Perchik Date: Wed, 24 Feb 2021 16:42:57 -0800 Subject: [PATCH 4/8] LWG3492 Minimal improvements to elements_view::iterator --- source/ranges.tex | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/ranges.tex b/source/ranges.tex index 0cc3e32c4a..3446fa32b0 100644 --- a/source/ranges.tex +++ b/source/ranges.tex @@ -6399,7 +6399,7 @@ { return get(*@\exposid{current_}@); } constexpr @\exposid{iterator}@& operator++(); - constexpr void operator++(int) requires (!@\libconcept{forward_range}@<@\exposid{Base}@>); + constexpr void operator++(int); constexpr @\exposid{iterator}@ operator++(int) requires @\libconcept{forward_range}@<@\exposid{Base}@>; constexpr @\exposid{iterator}@& operator--() requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>; @@ -6503,7 +6503,7 @@ \indexlibrarymember{operator++}{elements_view::iterator}% \begin{itemdecl} -constexpr void operator++(int) requires (!@\libconcept{forward_range}@<@\exposid{Base}@>); +constexpr void operator++(int); \end{itemdecl} \begin{itemdescr} From dcddfb0f9514a6a5a13c560cb5feb4d7239adeea Mon Sep 17 00:00:00 2001 From: Dawn Perchik Date: Wed, 24 Feb 2021 16:52:20 -0800 Subject: [PATCH 5/8] LWG3495 constexpr launder makes pointers to inactive members of unions usable --- source/support.tex | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/support.tex b/source/support.tex index 4998aa79d2..25a545e89e 100644 --- a/source/support.tex +++ b/source/support.tex @@ -3020,8 +3020,8 @@ \remarks An invocation of this function may be used in a core constant expression -whenever the value of its argument -may be used in a core constant expression. +if and only if the (converted) value of its argument +may be used in place of the function invocation. A byte of storage \placeholder{b} is reachable through a pointer value that points to an object \placeholder{Y} From 6deea4dd3fa27e309c8c36938a6355ba035e46f6 Mon Sep 17 00:00:00 2001 From: Dawn Perchik Date: Wed, 24 Feb 2021 17:23:24 -0800 Subject: [PATCH 6/8] LWG3500 join_view::iterator::operator->() is bogus --- source/ranges.tex | 37 ++++++++++++++++++------------------- 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/source/ranges.tex b/source/ranges.tex index 3446fa32b0..53be846adc 100644 --- a/source/ranges.tex +++ b/source/ranges.tex @@ -5056,16 +5056,17 @@ template struct join_view::@\exposid{iterator}@ { private: - using @\exposid{Parent}@ = @\exposid{maybe-const}@; // \expos - using @\exposid{Base}@ = @\exposid{maybe-const}@; // \expos + using @\exposid{Parent}@ = @\exposid{maybe-const}@; // \expos + using @\exposid{Base}@ = @\exposid{maybe-const}@; // \expos + using @\exposid{OuterIter}@ = iterator_t<@\exposid{Base}@>; // \expos + using @\exposid{InnerIter}@ = iterator_t>; // \expos static constexpr bool @\exposid{ref-is-glvalue}@ = // \expos is_reference_v>; - iterator_t<@\exposid{Base}@> @\exposid{outer_}@ = iterator_t<@\exposid{Base}@>(); // \expos - iterator_t> @\exposid{inner_}@ = // \expos - iterator_t>(); - @\exposid{Parent}@* @\exposid{parent_}@ = nullptr; // \expos + @\exposid{OuterIter}@ @\exposid{outer_}@ = @\exposid{OuterIter}@(); // \expos + @\exposid{InnerIter}@ @\exposid{inner_}@ = @\exposid{InnerIter}@(); // \expos + @\exposid{Parent}@* @\exposidnc{parent_}@ = nullptr; // \expos constexpr void @\exposid{satisfy}@(); // \expos public: @@ -5075,17 +5076,16 @@ using difference_type = @\seebelow@; @\exposid{iterator}@() = default; - constexpr @\exposid{iterator}@(@\exposid{Parent}@& parent, iterator_t<@\exposid{Base}@> outer); + constexpr @\exposid{iterator}@(@\exposid{Parent}@& parent, @\exposid{OuterIter}@ outer); constexpr @\exposid{iterator}@(@\exposid{iterator}@ i) requires Const && - @\libconcept{convertible_to}@, iterator_t<@\exposid{Base}@>> && - @\libconcept{convertible_to}@, - iterator_t>>; + @\libconcept{convertible_to}@, @\exposid{OuterIter}@> && + @\libconcept{convertible_to}@, @\exposid{InnerIter}@>; constexpr decltype(auto) operator*() const { return *@\exposid{inner_}@; } - constexpr iterator_t<@\exposid{Base}@> operator->() const - requires @\exposconcept{has-arrow}@> && @\libconcept{copyable}@>; + constexpr @\exposid{InnerIter}@ operator->() const + requires @\exposconcept{has-arrow}@<@\exposid{InnerIter}@> && @\libconcept{copyable}@<@\exposid{InnerIter}@>; constexpr @\exposid{iterator}@& operator++(); constexpr void operator++(int); @@ -5188,13 +5188,13 @@ return; } if constexpr (@\exposid{ref-is-glvalue}@) - @\exposid{inner_}@ = iterator_t>(); + @\exposid{inner_}@ = @\exposid{InnerIter}@(); \end{codeblock} \end{itemdescr} \indexlibraryctor{join_view::iterator}% \begin{itemdecl} -constexpr @\exposid{iterator}@(@\exposid{Parent}@& parent, iterator_t<@\exposid{Base}@> outer); +constexpr @\exposid{iterator}@(@\exposid{Parent}@& parent, @\exposid{OuterIter}@ outer); \end{itemdecl} \begin{itemdescr} @@ -5208,9 +5208,8 @@ \begin{itemdecl} constexpr @\exposid{iterator}@(@\exposid{iterator}@ i) requires Const && - @\libconcept{convertible_to}@, iterator_t<@\exposid{Base}@>> && - @\libconcept{convertible_to}@, - iterator_t>>; + @\libconcept{convertible_to}@, @\exposid{OuterIter}@> && + @\libconcept{convertible_to}@, @\exposid{InnerIter}@>; \end{itemdecl} \begin{itemdescr} @@ -5223,8 +5222,8 @@ \indexlibrarymember{operator->}{join_view::iterator}% \begin{itemdecl} -constexpr iterator_t<@\exposid{Base}@> operator->() const - requires @\exposconcept{has-arrow}@> && copyable>; +constexpr @\exposid{InnerIter}@ operator->() const + requires @\exposconcept{has-arrow}@<@\exposid{InnerIter}@> && @\libconcept{copyable}@<@\exposid{InnerIter}@>; \end{itemdecl} \begin{itemdescr} From 21de0b04fff1e4615a947f9f3df9b366e57202db Mon Sep 17 00:00:00 2001 From: Dawn Perchik Date: Wed, 24 Feb 2021 18:40:27 -0800 Subject: [PATCH 7/8] LWG3502 elements_view should not be allowed to return dangling references --- source/ranges.tex | 40 ++++++++++++++++++++++++++++++++++------ 1 file changed, 34 insertions(+), 6 deletions(-) diff --git a/source/ranges.tex b/source/ranges.tex index 53be846adc..2fcd89362a 100644 --- a/source/ranges.tex +++ b/source/ranges.tex @@ -6310,10 +6310,14 @@ { get(t) } -> convertible_to&>; }; + template + concept @\defexposconcept{returnable-element}@ = // \expos + is_reference_v || move_constructible>; template<@\libconcept{input_range}@ V, size_t N> requires @\libconcept{view}@ && @\exposconcept{has-tuple-element}@, N> && - @\exposconcept{has-tuple-element}@>, N> + @\exposconcept{has-tuple-element}@>, N> && + @\exposconcept{returnable-element}@, N> class elements_view : public view_interface> { public: elements_view() = default; @@ -6374,12 +6378,16 @@ namespace std::ranges { template<@\libconcept{input_range}@ V, size_t N> requires @\libconcept{view}@ && @\exposconcept{has-tuple-element}@, N> && - @\exposconcept{has-tuple-element}@>, N> + @\exposconcept{has-tuple-element}@>, N> && + @\exposconcept{returnable-element}@, N> template class elements_view::@\exposid{iterator}@ { // \expos using @\exposid{Base}@ = @\exposid{maybe-const}@; // \expos - iterator_t<@\exposid{Base}@> @\exposid{current_}@ = iterator_t<@\exposid{Base}@>(); + iterator_t<@\exposid{Base}@> @\exposid{current_}@ = iterator_t<@\exposid{Base}@>(); // \expos + + static constexpr decltype(auto) @\exposid{get-element}@(const iterator_t<@\exposid{Base}@>& i); // \expos + public: using iterator_category = typename iterator_traits>::iterator_category; using value_type = remove_cvref_t>>; @@ -6395,7 +6403,7 @@ constexpr iterator_t<@\exposid{Base}@> base() &&; constexpr decltype(auto) operator*() const - { return get(*@\exposid{current_}@); } + { return @\exposid{get-element}@(@\exposid{current_}@); } constexpr @\exposid{iterator}@& operator++(); constexpr void operator++(int); @@ -6411,7 +6419,7 @@ constexpr decltype(auto) operator[](difference_type n) const requires @\libconcept{random_access_range}@<@\exposid{Base}@> - { return get(*(@\exposid{current_}@ + n)); } + { return @\exposid{get-element}@(@\exposid{current_}@ + n); } friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) requires @\libconcept{equality_comparable}@>; @@ -6439,6 +6447,25 @@ } \end{codeblock} +\indexlibrarymember{\exposid{get-element}}{elements_view::iterator}% +\begin{itemdecl} +static constexpr decltype(auto) @\exposid{get-element}@(const iterator_t<@\exposid{Base}@>& i); // \expos +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +if constexpr (is_reference_v>) { + return get(*i); +} else { + using E = remove_cv_t>>; + return static_cast(get(*i)); +} +\end{codeblock} +\end{itemdescr} + \indexlibraryctor{elements_view::iterator}% \begin{itemdecl} constexpr explicit @\exposid{iterator}@(iterator_t<@\exposid{Base}@> current); @@ -6717,7 +6744,8 @@ namespace std::ranges { template<@\libconcept{input_range}@ V, size_t N> requires @\libconcept{view}@ && @\placeholder{has-tuple-element}@, N> && - @\placeholder{has-tuple-element}@>, N> + @\placeholder{has-tuple-element}@>, N> && + @\exposconcept{returnable-element}@, N> template class elements_view::@\exposid{sentinel}@ { // \expos private: From a0c8e90a9a6b64e99f681ded078c78abd8defbbb Mon Sep 17 00:00:00 2001 From: Dawn Perchik Date: Wed, 24 Feb 2021 18:45:07 -0800 Subject: [PATCH 8/8] LWG3505 split_view::outer-iterator::operator++ misspecified --- source/ranges.tex | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/source/ranges.tex b/source/ranges.tex index 2fcd89362a..4477268a95 100644 --- a/source/ranges.tex +++ b/source/ranges.tex @@ -5674,11 +5674,17 @@ if (@\placeholder{current}@ == end) return *this; const auto [pbegin, pend] = subrange{@\exposid{parent_}@->@\exposid{pattern_}@}; if (pbegin == pend) ++@\placeholder{current}@; +else if constexpr (@\exposconcept{tiny-range}@) { + @\placeholder{current}@ = ranges::find(std::move(@\placeholder{current}@), end, *pbegin); + if (@\placeholder{current}@ != end) { + ++@\placeholder{current}@; + } +} else { do { - auto [b, p] = ranges::mismatch(std::move(@\placeholder{current}@), end, pbegin, pend); - @\placeholder{current}@ = std::move(b); + auto [b, p] = ranges::mismatch(@\placeholder{current}@, end, pbegin, pend); if (p == pend) { + @\placeholder{current}@ = b; break; // The pattern matched; skip it } } while (++@\placeholder{current}@ != end);