From b1c1dcde17d8b147ec19d44096fc5f15a30f2dd1 Mon Sep 17 00:00:00 2001 From: Dawn Perchik Date: Fri, 17 Feb 2023 16:01:17 -0800 Subject: [PATCH 1/3] P2164R9 views::enumerate Editorial changes: * Added missing "views::" qualification in example * Added missing "friend" in itemdecls * Fixed "pos_" to "i.pos_" in iter_move definition * Removed erroneous and unused default argument "pos = 0" Fixes NB FR 021, US 108 (C++23 CD). --- source/ranges.tex | 561 +++++++++++++++++++++++++++++++++++++++++++++ source/support.tex | 1 + 2 files changed, 562 insertions(+) diff --git a/source/ranges.tex b/source/ranges.tex index b408a199db..9b16ecf074 100644 --- a/source/ranges.tex +++ b/source/ranges.tex @@ -432,6 +432,17 @@ inline constexpr auto @\libmember{values}{views}@ = elements<1>; // freestanding } + // \ref{range.enumerate}, enumerate view + template<@\libconcept{input_range}@ View> + requires @\libconcept{view}@ + class enumerate_view; // freestanding + + template + inline constexpr bool enable_borrowed_range> = // freestanding + enable_borrowed_range; + + namespace views { inline constexpr @\unspecnc@ enumerate = @\unspecnc@; } // freestanding + // \ref{range.zip}, zip view template<@\libconcept{input_range}@... Views> requires (@\libconcept{view}@ && ...) && (sizeof...(Views) > 0) @@ -1634,6 +1645,11 @@ template concept @\defexposconceptnc{different-from}@ = // \expos !@\libconcept{same_as}@, remove_cvref_t>; + +template + concept @\defexposconceptnc{range-with-movable-references}@ = // \expos + @\libconcept{input_range}@ && @\libconcept{move_constructible}@> && + @\libconcept{move_constructible}@>; \end{codeblock} \rSec2[view.interface]{View interface} @@ -9462,6 +9478,551 @@ Equivalent to: \tcode{return x.\exposid{end_} - y.\exposid{current_};} \end{itemdescr} +\rSec2[range.enumerate]{Enumerate view} + +\rSec3[range.enumerate.overview]{Overview} + +\pnum +\indexlibraryglobal{enumerate_view}% +\tcode{enumerate_view} is a view whose +elements represent both the position and value from +a sequence of elements. + +\pnum +\indexlibrarymember{enumerate}{views}% +The name \tcode{views::enumerate} denotes a range adaptor object. +Given a subexpression \tcode{E}, +the expression \tcode{views::enumerate(E)} is expression-equivalent to +\tcode{enumerate_view>(E)}. +\begin{example} +\begin{codeblock} +vector vec{ 1, 2, 3 }; +for (auto [index, value] : views::enumerate(vec)) + cout << index << ":" << value << ' '; // prints \tcode{0:1 1:2 2:3} +\end{codeblock} +\end{example} + +\rSec3[range.enumerate.view]{Class template \tcode{enumerate_view}} + +\indexlibrarymember{begin}{enumerate_view}% +\indexlibrarymember{end}{enumerate_view}% +\indexlibrarymember{size}{enumerate_view}% +\begin{codeblock} +namespace std::ranges { + template<@\libconcept{view}@ V> + requires @\exposconcept{range-with-movable-references}@ + class enumerate_view : public view_interface> { + V @\exposidnc{base_}@ = V(); // \expos + + // \ref{range.enumerate.iterator}, class template \tcode{enumerate_view::\exposid{iterator}} + template + class @\exposidnc{iterator}@; // \expos + + // \ref{range.enumerate.sentinel}, class template \tcode{enumerate_view::\exposid{sentinel}} + template + class @\exposidnc{sentinel}@; // \expos + + public: + constexpr enumerate_view() requires @\libconcept{default_initializable}@ = default; + constexpr explicit enumerate_view(V base); + + constexpr auto begin() requires (!@\exposconcept{simple-view}@) + { return @\exposid{iterator}@(ranges::begin(@\exposid{base_}@), 0); } + constexpr auto begin() const requires @\exposconcept{range-with-movable-references}@ + { return @\exposid{iterator}@(ranges::begin(@\exposid{base_}@), 0); } + + constexpr auto end() requires (!@\exposconcept{simple-view}@) { + if constexpr (@\libconcept{common_range}@ && @\libconcept{sized_range}@) + return @\exposid{iterator}@(ranges::end(@\exposid{base_}@), ranges::distance(@\exposid{base_}@)); + else + return @\exposid{sentinel}@(ranges::end(@\exposid{base_}@)); + } + constexpr auto end() const requires @\exposconcept{range-with-movable-references}@ { + if constexpr (@\libconcept{common_range}@ && @\libconcept{sized_range}@) + return @\exposid{iterator}@(ranges::end(@\exposid{base_}@), ranges::distance(@\exposid{base_}@)); + else + return @\exposid{sentinel}@(ranges::end(@\exposid{base_}@)); + } + + constexpr auto size() + requires @\libconcept{sized_range}@ + { return ranges::size(@\exposid{base_}@); } + constexpr auto size() const + requires @\libconcept{sized_range}@ + { return ranges::size(@\exposid{base_}@); } + + constexpr V base() const & requires @\libconcept{copy_constructible}@ { return @\exposid{base_}@; } + constexpr V base() && { return std::move(@\exposid{base_}@); } + }; + + template + enumerate_view(R&&) -> enumerate_view>; +} +\end{codeblock} + +\begin{itemdecl} +constexpr explicit enumerate_view(V base); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \exposid{base_} with \tcode{std::move(base)}. +\end{itemdescr} + +\rSec3[range.enumerate.iterator]{Class template \tcode{enumerate_view::\exposid{iterator}}} + +\indexlibraryglobal{enumerate_view::\exposid{iterator}}% +\begin{codeblock} +namespace std::ranges { + template<@\libconcept{view}@ V> + requires @\exposconcept{range-with-movable-references}@ + template + class enumerate_view::@\exposid{iterator}@ { + using @\exposidnc{Base}@ = @\exposidnc{maybe-const}@; // \expos + + public: + using iterator_category = input_iterator_tag; + using iterator_concept = @\seebelow@; + using difference_type = range_difference_t<@\exposid{Base}@>; + using value_type = tuple>; + + private: + using @\exposidnc{reference-type}@ = // \expos + tuple>; + iterator_t<@\exposidnc{Base}@> @\exposidnc{current_}@ = iterator_t<@\exposidnc{Base}@>(); // \expos + difference_type @\exposidnc{pos_}@ = 0; // \expos + + constexpr explicit + @\exposidnc{iterator}@(iterator_t<@\exposidnc{Base}@> current, difference_type pos); // \expos + + public: + @\exposid{iterator}@() requires @\libconcept{default_initializable}@> = default; + constexpr @\exposid{iterator}@(@\exposid{iterator}@ i) + requires Const && @\libconcept{convertible_to}@, iterator_t<@\exposid{Base}@>>; + + constexpr const iterator_t<@\exposid{Base}@>& base() const & noexcept; + constexpr iterator_t<@\exposid{Base}@> base() &&; + + constexpr difference_type index() const noexcept; + + constexpr auto operator*() const { + return @\exposid{reference-type}@(@\exposid{pos_}@, *@\exposid{current_}@); + } + + constexpr @\exposid{iterator}@& operator++(); + 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}@>; + constexpr @\exposid{iterator}@ operator--(int) requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>; + + constexpr @\exposid{iterator}@& operator+=(difference_type x) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + constexpr @\exposid{iterator}@& operator-=(difference_type x) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + + constexpr auto operator[](difference_type n) const + requires @\libconcept{random_access_range}@<@\exposid{Base}@> + { return @\exposid{reference-type}@(@\exposid{pos_}@ + n, @\exposid{current_}@[n]); } + + friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) noexcept; + friend constexpr strong_ordering operator<=>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) noexcept; + + friend constexpr @\exposid{iterator}@ operator+(const @\exposid{iterator}@& x, difference_type y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + friend constexpr @\exposid{iterator}@ operator+(difference_type x, const @\exposid{iterator}@& y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + friend constexpr @\exposid{iterator}@ operator-(const @\exposid{iterator}@& x, difference_type y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; + friend constexpr difference_type operator-(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y); + + friend constexpr auto iter_move(const @\exposid{iterator}@& i) + noexcept(noexcept(ranges::iter_move(i.@\exposid{current_}@)) && + is_nothrow_move_constructible_v>) { + return tuple>(i.@\exposid{pos_}@, ranges::iter_move(i.@\exposid{current_}@)); + } + }; +} +\end{codeblock} + +\pnum +The member \grammarterm{typedef-name} +\tcode{\exposid{iterator}::iterator_concept} +is defined as follows: +\begin{itemize} +\item +If \exposid{Base} models \libconcept{random_access_range}, +then \tcode{iterator_concept} denotes \tcode{random_access_iterator_tag}. +\item +Otherwise, if \exposid{Base} models \libconcept{bidirectional_range}, +then \tcode{iterator_concept} denotes \tcode{bidirectional_iterator_tag}. +\item +Otherwise, if \exposid{Base} models \libconcept{forward_range}, +then \tcode{iterator_concept} denotes \tcode{forward_iterator_tag}. +\item +Otherwise, \tcode{iterator_concept} denotes \tcode{input_iterator_tag}. +\end{itemize} + +\indexlibraryctor{enumerate_view::\exposid{iterator}}% +\begin{itemdecl} +constexpr explicit @\exposid{iterator}@(iterator_t<@\exposid{Base}@> current, difference_type pos); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \exposid{current_} with \tcode{std::move(current)} and +\exposid{pos_} with \tcode{pos}. +\end{itemdescr} + +\indexlibraryctor{enumerate_view::\exposid{iterator}}% +\begin{itemdecl} +constexpr @\exposid{iterator}@(@\exposid{iterator}@ i) + requires Const && @\libconcept{convertible_to}@, iterator_t<@\exposid{Base}@>>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \exposid{current_} with \tcode{std::move(i.\exposid{current_})} and +\exposid{pos_} with \tcode{i.\exposid{pos_}}. +\end{itemdescr} + +\indexlibrarymember{base}{enumerate_view::\exposid{iterator}}% +\begin{itemdecl} +constexpr const iterator_t<@\exposid{Base}@>& base() const & noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return \exposid{current_};} +\end{itemdescr} + +\indexlibrarymember{base}{enumerate_view::\exposid{iterator}}% +\begin{itemdecl} +constexpr iterator_t<@\exposid{Base}@> base() &&; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return std::move(\exposid{current_});} +\end{itemdescr} + +\indexlibrarymember{index}{enumerate_view::\exposid{iterator}}% +\begin{itemdecl} +constexpr difference_type index() const noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return \exposid{pos_};} +\end{itemdescr} + +\indexlibrarymember{operator++}{enumerate_view::\exposid{iterator}}% +\begin{itemdecl} +constexpr @\exposid{iterator}@& operator++(); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +++@\exposid{current_}@; +++@\exposid{pos_}@; +return *this; +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{operator++}{enumerate_view::\exposid{iterator}}% +\begin{itemdecl} +constexpr void operator++(int); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to \tcode{++*this}. +\end{itemdescr} + +\indexlibrarymember{operator++}{enumerate_view::\exposid{iterator}}% +\begin{itemdecl} +constexpr @\exposid{iterator}@ operator++(int) requires @\libconcept{forward_range}@<@\exposid{Base}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +auto temp = *this; +++*this; +return temp; +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{operator--}{enumerate_view::\exposid{iterator}}% +\begin{itemdecl} +constexpr @\exposid{iterator}@& operator--() requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +--@\exposid{current_}@; +--@\exposid{pos_}@; +return *this; +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{operator--}{enumerate_view::\exposid{iterator}}% +\begin{itemdecl} +constexpr @\exposid{iterator}@ operator--(int) requires @\libconcept{bidirectional_range}@<@\exposid{Base}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +auto temp = *this; +--*this; +return temp; +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{operator+=}{enumerate_view::\exposid{iterator}}% +\begin{itemdecl} +constexpr @\exposid{iterator}@& operator+=(difference_type n) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +@\exposid{current_}@ += n; +@\exposid{pos_}@ += n; +return *this; +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{operator-=}{enumerate_view::\exposid{iterator}}% +\begin{itemdecl} +constexpr @\exposid{iterator}@& operator-=(difference_type n) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +@\exposid{current_}@ -= n; +@\exposid{pos_}@ -= n; +return *this; +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{operator==}{enumerate_view::\exposid{iterator}}% +\begin{itemdecl} +friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return x.\exposid{pos_} == y.\exposid{pos_};} +\end{itemdescr} + +\indexlibrarymember{operator<=>}{enumerate_view::\exposid{iterator}}% +\begin{itemdecl} +friend constexpr strong_ordering operator<=>(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y) noexcept; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return x.\exposid{pos_} <=> y.\exposid{pos_};} +\end{itemdescr} + +\indexlibrarymember{operator+}{enumerate_view::\exposid{iterator}}% +\begin{itemdecl} +friend constexpr @\exposid{iterator}@ operator+(const @\exposid{iterator}@& x, difference_type y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +auto temp = x; +temp += y; +return temp; +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{operator+}{enumerate_view::\exposid{iterator}}% +\begin{itemdecl} +friend constexpr @\exposid{iterator}@ operator+(difference_type x, const @\exposid{iterator}@& y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return y + x;} +\end{itemdescr} + +\indexlibrarymember{operator-}{enumerate_view::\exposid{iterator}}% +\begin{itemdecl} +friend constexpr @\exposid{iterator}@ operator-(const @\exposid{iterator}@& x, difference_type y) + requires @\libconcept{random_access_range}@<@\exposid{Base}@>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: +\begin{codeblock} +auto temp = x; +temp -= y; +return temp; +\end{codeblock} +\end{itemdescr} + +\indexlibrarymember{operator-}{enumerate_view::\exposid{iterator}}% +\begin{itemdecl} +friend constexpr difference_type operator-(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return x.\exposid{pos_} - y.\exposid{pos_};} +\end{itemdescr} + +\rSec3[range.enumerate.sentinel]{Class template \tcode{enumerate_view::\exposid{sentinel}}} + +\indexlibraryglobal{enumerate_view::\exposid{sentinel}}% +\begin{codeblock} +namespace std::ranges { + template<@\libconcept{view}@ V> + requires @\exposconcept{range-with-movable-references}@ + template + class enumerate_view::@\exposidnc{sentinel}@ { // \expos + using @\exposidnc{Base}@ = @\exposidnc{maybe-const}@; // \expos + sentinel_t<@\exposidnc{Base}@> @\exposidnc{end_}@ = sentinel_t<@\exposidnc{Base}@>(); // \expos + constexpr explicit @\exposid{sentinel}@(sentinel_t<@\exposid{Base}@> end); + + public: + @\exposid{sentinel}@() = default; + constexpr @\exposid{sentinel}@(@\exposid{sentinel}@ other) + requires Const && @\libconcept{convertible_to}@, sentinel_t<@\exposid{Base}@>>; + + constexpr sentinel_t<@\exposid{Base}@> base() const; + + template + requires @\libconcept{sentinel_for}@, iterator_t<@\exposid{maybe-const}@>> + friend constexpr bool operator==(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); + + template + requires @\libconcept{sized_sentinel_for}@, iterator_t<@\exposid{maybe-const}@>> + friend constexpr range_difference_t<@\exposid{maybe-const}@> + operator-(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); + + template + requires @\libconcept{sized_sentinel_for}@, iterator_t<@\exposid{maybe-const}@>> + friend constexpr range_difference_t<@\exposid{maybe-const}@> + operator-(const @\exposid{sentinel}@& x, const @\exposid{iterator}@& y); + }; +} +\end{codeblock} + +\indexlibraryctor{enumerate_view::\exposid{sentinel}}% +\begin{itemdecl} +constexpr explicit @\exposid{sentinel}@(sentinel_t<@\exposid{Base}@> end); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \exposid{end_} with \tcode{std::move(end)}. +\end{itemdescr} + +\indexlibraryctor{enumerate_view::\exposid{sentinel}}% +\begin{itemdecl} +constexpr @\exposid{sentinel}@(@\exposid{sentinel}@ other) + requires Const && @\libconcept{convertible_to}@, sentinel_t<@\exposid{Base}@>>; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Initializes \exposid{end_} with \tcode{std::move(other.\exposid{end_})}. +\end{itemdescr} + +\indexlibrarymember{base}{enumerate_view::\exposid{sentinel}}% +\begin{itemdecl} +constexpr sentinel_t<@\exposid{Base}@> base() const; +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return \exposid{end_};} +\end{itemdescr} + +\indexlibrarymember{operator==}{enumerate_view::\exposid{sentinel}}% +\begin{itemdecl} +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} +\pnum +\effects +Equivalent to: \tcode{return x.\exposid{current_} == y.\exposid{end_};} +\end{itemdescr} + +\indexlibrarymember{operator-}{enumerate_view::\exposid{sentinel}}% +\begin{itemdecl} +template + requires @\libconcept{sized_sentinel_for}@, iterator_t<@\exposid{maybe-const}@>> +friend constexpr range_difference_t<@\exposid{maybe-const}@> + operator-(const @\exposid{iterator}@& x, const @\exposid{sentinel}@& y); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return x.\exposid{current_} - y.\exposid{end_};} +\end{itemdescr} + +\indexlibrarymember{operator-}{enumerate_view::\exposid{sentinel}}% +\begin{itemdecl} +template + requires @\libconcept{sized_sentinel_for}@, iterator_t<@\exposid{maybe-const}@>> +friend constexpr range_difference_t<@\exposid{maybe-const}@> + operator-(const @\exposid{sentinel}@& x, const @\exposid{iterator}@& y); +\end{itemdecl} + +\begin{itemdescr} +\pnum +\effects +Equivalent to: \tcode{return x.\exposid{end_} - y.\exposid{current_};} +\end{itemdescr} + \rSec2[range.zip]{Zip view} \rSec3[range.zip.overview]{Overview} diff --git a/source/support.tex b/source/support.tex index 80390e4596..3d0163861b 100644 --- a/source/support.tex +++ b/source/support.tex @@ -690,6 +690,7 @@ #define @\defnlibxname{cpp_lib_ranges_chunk}@ 202202L // also in \libheader{ranges} #define @\defnlibxname{cpp_lib_ranges_chunk_by}@ 202202L // also in \libheader{ranges} #define @\defnlibxname{cpp_lib_ranges_contains}@ 202207L // also in \libheader{algorithm} +#define @\defnlibxname{cpp_lib_ranges_enumerate}@ 202302L // also in \libheader{ranges}, \libheader{version} #define @\defnlibxname{cpp_lib_ranges_find_last}@ 202207L // also in \libheader{algorithm} #define @\defnlibxname{cpp_lib_ranges_fold}@ 202207L // also in \libheader{algorithm} #define @\defnlibxname{cpp_lib_ranges_iota}@ 202202L // also in \libheader{numeric} From d2ba9e375911c7994454fcb72c7d2f3cdb7ba7d4 Mon Sep 17 00:00:00 2001 From: Dawn Perchik Date: Tue, 21 Feb 2023 16:33:18 -0800 Subject: [PATCH 2/3] [ranges.syn] Remove "inline" from constexpr variable template --- source/ranges.tex | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/ranges.tex b/source/ranges.tex index 9b16ecf074..e988472544 100644 --- a/source/ranges.tex +++ b/source/ranges.tex @@ -438,7 +438,7 @@ class enumerate_view; // freestanding template - inline constexpr bool enable_borrowed_range> = // freestanding + constexpr bool enable_borrowed_range> = // freestanding enable_borrowed_range; namespace views { inline constexpr @\unspecnc@ enumerate = @\unspecnc@; } // freestanding From 1ed375ade668fa197524714eb9bc6d12d6ebd61d Mon Sep 17 00:00:00 2001 From: Dawn Perchik Date: Tue, 21 Feb 2023 17:45:38 -0800 Subject: [PATCH 3/3] [range.enumerate.sentinel] Move \expos comment to the right place The comment was attached to the line of the definition of sentinel's class, but it should appear on the line of the declaration of its first constructor. --- source/ranges.tex | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/source/ranges.tex b/source/ranges.tex index e988472544..6c2a49b30d 100644 --- a/source/ranges.tex +++ b/source/ranges.tex @@ -9919,10 +9919,10 @@ template<@\libconcept{view}@ V> requires @\exposconcept{range-with-movable-references}@ template - class enumerate_view::@\exposidnc{sentinel}@ { // \expos + class enumerate_view::@\exposid{sentinel}@ { using @\exposidnc{Base}@ = @\exposidnc{maybe-const}@; // \expos sentinel_t<@\exposidnc{Base}@> @\exposidnc{end_}@ = sentinel_t<@\exposidnc{Base}@>(); // \expos - constexpr explicit @\exposid{sentinel}@(sentinel_t<@\exposid{Base}@> end); + constexpr explicit @\exposidnc{sentinel}@(sentinel_t<@\exposidnc{Base}@> end); // \expos public: @\exposid{sentinel}@() = default;