Skip to content

Commit 06be8f8

Browse files
authored
Merge 2025-02 LWG Motion 3
P3137R3 views::to_input
2 parents adb8d1c + 141917a commit 06be8f8

File tree

2 files changed

+295
-0
lines changed

2 files changed

+295
-0
lines changed

source/ranges.tex

+294
Original file line numberDiff line numberDiff line change
@@ -551,6 +551,17 @@
551551
class cache_latest_view;
552552

553553
namespace views { inline constexpr @\unspec@ cache_latest = @\unspec@; }
554+
555+
// \ref{range.to.input}, to input view
556+
template<@\libconcept{input_range}@ V>
557+
requires @\libconcept{view}@<V>
558+
class to_input_view;
559+
560+
template<class V>
561+
constexpr bool enable_borrowed_range<to_input_view<V>> =
562+
enable_borrowed_range<V>;
563+
564+
namespace views { inline constexpr @\unspec@ to_input = @\unspec@; }
554565
}
555566

556567
namespace std {
@@ -17088,6 +17099,289 @@
1708817099
\tcode{x.\exposid{end_} - y.\exposid{current_}}.
1708917100
\end{itemdescr}
1709017101

17102+
\rSec2[range.to.input]{To input view}
17103+
17104+
\rSec3[range.to.input.overview]{Overview}
17105+
17106+
\pnum
17107+
\tcode{to_input_view} presents a view of an underlying sequence
17108+
as an input-only non-common range.
17109+
\begin{note}
17110+
This is useful to avoid overhead
17111+
that can be necessary to provide support for the operations
17112+
needed for greater iterator strength.
17113+
\end{note}
17114+
17115+
\pnum
17116+
The name \tcode{views::to_input} denotes
17117+
a range adaptor object\iref{range.adaptor.object}.
17118+
Let \tcode{E} be an expression and let \tcode{T} be \tcode{decltype((E))}.
17119+
The expression \tcode{views::to_input(E)} is expression-equivalent to:
17120+
\begin{itemize}
17121+
\item
17122+
\tcode{views::all(E)}
17123+
if \tcode{T} models \libconcept{input_range},
17124+
does not satisfy \libconcept{common_range}, and
17125+
does not satisfy \libconcept{forward_range}.
17126+
\item
17127+
Otherwise, \tcode{to_input_view(E)}.
17128+
\end{itemize}
17129+
17130+
\rSec3[range.to.input.view]{Class template \tcode{to_input_view}}
17131+
17132+
\begin{codeblock}
17133+
template<@\libconcept{input_range}@ V>
17134+
requires @\libconcept{view}@<V>
17135+
class to_input_view : public view_interface<to_input_view<V>> {
17136+
V @\exposid{base_}@ = V(); // \expos
17137+
17138+
template<bool Const> class @\exposid{iterator}@; // \expos
17139+
17140+
public:
17141+
to_input_view() requires @\libconcept{default_initializable}@<V> = default;
17142+
constexpr explicit to_input_view(V base);
17143+
17144+
constexpr V base() const & requires @\libconcept{copy_constructible}@<V> { return @\exposid{base_}@; }
17145+
constexpr V base() && { return std::move(@\exposid{base_}@); }
17146+
17147+
constexpr auto begin() requires (!@\exposconcept{simple-view}@<V>);
17148+
constexpr auto begin() const requires @\libconcept{range}@<const V>;
17149+
17150+
constexpr auto end() requires (!@\exposconcept{simple-view}@<V>);
17151+
constexpr auto end() const requires @\libconcept{range}@<const V>;
17152+
17153+
constexpr auto size() requires @\libconcept{sized_range}@<V>;
17154+
constexpr auto size() const requires @\libconcept{sized_range}@<const V>;
17155+
};
17156+
17157+
template<class R>
17158+
to_input_view(R&&) -> to_input_view<views::all_t<R>>;
17159+
\end{codeblock}
17160+
17161+
\begin{itemdecl}
17162+
constexpr explicit to_input_view(V base);
17163+
\end{itemdecl}
17164+
17165+
\begin{itemdescr}
17166+
\pnum
17167+
\effects
17168+
Initializes \exposid{base_} with \tcode{std::move(base)}.
17169+
\end{itemdescr}
17170+
17171+
\begin{itemdecl}
17172+
constexpr auto begin() requires (!@\exposconcept{simple-view}@<V>);
17173+
\end{itemdecl}
17174+
17175+
\begin{itemdescr}
17176+
\pnum
17177+
\effects
17178+
Equivalent to: \tcode{return \exposid{iterator}<false>(ranges::begin(\exposid{base_}));}
17179+
\end{itemdescr}
17180+
17181+
\begin{itemdecl}
17182+
constexpr auto begin() const requires @\libconcept{range}@<const V>;
17183+
\end{itemdecl}
17184+
17185+
\begin{itemdescr}
17186+
\pnum
17187+
\effects
17188+
Equivalent to: \tcode{return \exposid{iterator}<true>(ranges::begin(\exposid{base_}));}
17189+
\end{itemdescr}
17190+
17191+
\begin{itemdecl}
17192+
constexpr auto end() requires (!@\exposconcept{simple-view}@<V>);
17193+
constexpr auto end() const requires @\libconcept{range}@<const V>;
17194+
\end{itemdecl}
17195+
17196+
\begin{itemdescr}
17197+
\pnum
17198+
\effects
17199+
Equivalent to: \tcode{return ranges::end(\exposid{base_});}
17200+
\end{itemdescr}
17201+
17202+
\begin{itemdecl}
17203+
constexpr auto size() requires @\libconcept{sized_range}@<V>;
17204+
constexpr auto size() const requires @\libconcept{sized_range}@<const V>;
17205+
\end{itemdecl}
17206+
17207+
\begin{itemdescr}
17208+
\pnum
17209+
\effects
17210+
Equivalent to: \tcode{return ranges::size(\exposid{base_});}
17211+
\end{itemdescr}
17212+
17213+
\rSec3[range.to.input.iterator]{Class template \tcode{to_input_view::\exposid{iterator}}}
17214+
17215+
\begin{codeblock}
17216+
namespace std::ranges {
17217+
template<@\libconcept{input_range}@ V>
17218+
requires @\libconcept{view}@<V>
17219+
template<bool Const>
17220+
class to_input_view<V>::@\exposid{iterator}@ {
17221+
using @\exposid{Base}@ = @\exposid{maybe-const}@<Const, V>; // \expos
17222+
17223+
iterator_t<@\exposid{Base}@> @\exposid{current_}@ = iterator_t<@\exposid{Base}@>(); // \expos
17224+
17225+
constexpr explicit @\exposid{iterator}@(iterator_t<@\exposid{Base}@> current); // \expos
17226+
17227+
public:
17228+
using difference_type = range_difference_t<@\exposid{Base}@>;
17229+
using value_type = range_value_t<@\exposid{Base}@>;
17230+
using iterator_concept = input_iterator_tag;
17231+
17232+
@\exposid{iterator}@() requires @\libconcept{default_initializable}@<iterator_t<@\exposid{Base}@>> = default;
17233+
17234+
@\exposid{iterator}@(@\exposid{iterator}@&&) = default;
17235+
@\exposid{iterator}@& operator=(@\exposid{iterator}@&&) = default;
17236+
17237+
constexpr @\exposid{iterator}@(@\exposid{iterator}@<!Const> i)
17238+
requires Const && @\libconcept{convertible_to}@<iterator_t<V>, iterator_t<@\exposid{Base}@>>;
17239+
17240+
constexpr iterator_t<@\exposid{Base}@> base() &&;
17241+
constexpr const iterator_t<@\exposid{Base}@>& base() const & noexcept;
17242+
17243+
constexpr decltype(auto) operator*() const { return *@\exposid{current_}@; }
17244+
17245+
constexpr @\exposid{iterator}@& operator++();
17246+
constexpr void operator++(int);
17247+
17248+
friend constexpr bool operator==(const @\exposid{iterator}@& x, const sentinel_t<@\exposid{Base}@>& y);
17249+
17250+
friend constexpr difference_type operator-(const sentinel_t<@\exposid{Base}@>& y, const @\exposid{iterator}@& x)
17251+
requires @\libconcept{sized_sentinel_for}@<sentinel_t<@\exposid{Base}@>, iterator_t<@\exposid{Base}@>>;
17252+
friend constexpr difference_type operator-(const @\exposid{iterator}@& x, const sentinel_t<@\exposid{Base}@>& y)
17253+
requires @\libconcept{sized_sentinel_for}@<sentinel_t<@\exposid{Base}@>, iterator_t<@\exposid{Base}@>>;
17254+
17255+
friend constexpr range_rvalue_reference_t<@\exposid{Base}@> iter_move(const @\exposid{iterator}@& i)
17256+
noexcept(noexcept(ranges::iter_move(i.@\exposid{current_}@)));
17257+
17258+
friend constexpr void iter_swap(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
17259+
noexcept(noexcept(ranges::iter_swap(x.@\exposid{current_}@, y.@\exposid{current_}@)))
17260+
requires @\libconcept{indirectly_swappable}@<iterator_t<@\exposid{Base}@>>;
17261+
};
17262+
}
17263+
\end{codeblock}
17264+
17265+
\begin{itemdecl}
17266+
constexpr explicit @\exposid{iterator}@(iterator_t<@\exposid{Base}@> current);
17267+
\end{itemdecl}
17268+
17269+
\begin{itemdescr}
17270+
\pnum
17271+
\effects
17272+
Initializes \exposid{current_} with \tcode{std::move(current)}.
17273+
\end{itemdescr}
17274+
17275+
\begin{itemdecl}
17276+
constexpr @\exposid{iterator}@(@\exposid{iterator}@<!Const> i)
17277+
requires Const && @\libconcept{convertible_to}@<iterator_t<V>, iterator_t<@\exposid{Base}@>>;
17278+
\end{itemdecl}
17279+
17280+
\begin{itemdescr}
17281+
\pnum
17282+
\effects
17283+
Initializes \exposid{current_} with \tcode{std::move(i.\exposid{current_})}.
17284+
\end{itemdescr}
17285+
17286+
\begin{itemdecl}
17287+
constexpr iterator_t<@\exposid{Base}@> base() &&;
17288+
\end{itemdecl}
17289+
17290+
\begin{itemdescr}
17291+
\pnum
17292+
\returns
17293+
\tcode{std::move(\exposid{current_)}}.
17294+
\end{itemdescr}
17295+
17296+
\begin{itemdecl}
17297+
constexpr const iterator_t<@\exposid{Base}@>& base() const & noexcept;
17298+
\end{itemdecl}
17299+
17300+
\begin{itemdescr}
17301+
\pnum
17302+
\returns
17303+
\exposid{current_}.
17304+
\end{itemdescr}
17305+
17306+
\begin{itemdecl}
17307+
constexpr @\exposid{iterator}@& operator++();
17308+
\end{itemdecl}
17309+
17310+
\begin{itemdescr}
17311+
\pnum
17312+
\effects
17313+
Equivalent to:
17314+
\begin{codeblock}
17315+
++@\exposid{current_}@;
17316+
return *this;
17317+
\end{codeblock}
17318+
\end{itemdescr}
17319+
17320+
\begin{itemdecl}
17321+
constexpr void operator++(int);
17322+
\end{itemdecl}
17323+
17324+
\begin{itemdescr}
17325+
\pnum
17326+
\effects
17327+
Equivalent to: \tcode{++*this;}
17328+
\end{itemdescr}
17329+
17330+
\begin{itemdecl}
17331+
friend constexpr bool operator==(const @\exposid{iterator}@& x, const sentinel_t<@\exposid{Base}@>& y);
17332+
\end{itemdecl}
17333+
17334+
\begin{itemdescr}
17335+
\pnum
17336+
\returns
17337+
\tcode{x.\exposid{current_} == y}.
17338+
\end{itemdescr}
17339+
17340+
\begin{itemdecl}
17341+
friend constexpr difference_type operator-(const sentinel_t<@\exposid{Base}@>& y, const @\exposid{iterator}@& x)
17342+
requires @\libconcept{sized_sentinel_for}@<sentinel_t<@\exposid{Base}@>, iterator_t<@\exposid{Base}@>>;
17343+
\end{itemdecl}
17344+
17345+
\begin{itemdescr}
17346+
\pnum
17347+
\returns
17348+
\tcode{y - x.\exposid{current_}}.
17349+
\end{itemdescr}
17350+
17351+
\begin{itemdecl}
17352+
friend constexpr difference_type operator-(const @\exposid{iterator}@& x, const sentinel_t<@\exposid{Base}@>& y)
17353+
requires @\libconcept{sized_sentinel_for}@<sentinel_t<@\exposid{Base}@>, iterator_t<@\exposid{Base}@>>;
17354+
\end{itemdecl}
17355+
17356+
\begin{itemdescr}
17357+
\pnum
17358+
\returns
17359+
\tcode{x.\exposid{current_} - y}.
17360+
\end{itemdescr}
17361+
17362+
\begin{itemdecl}
17363+
friend constexpr range_rvalue_reference_t<@\exposid{Base}@> iter_move(const @\exposid{iterator}@& i)
17364+
noexcept(noexcept(ranges::iter_move(i.@\exposid{current_}@)));
17365+
\end{itemdecl}
17366+
17367+
\begin{itemdescr}
17368+
\pnum
17369+
\effects
17370+
Equivalent to: \tcode{return ranges::iter_move(i.\exposid{current_});}
17371+
\end{itemdescr}
17372+
17373+
\begin{itemdecl}
17374+
friend constexpr void iter_swap(const @\exposid{iterator}@& x, const @\exposid{iterator}@& y)
17375+
noexcept(noexcept(ranges::iter_swap(x.@\exposid{current_}@, y.@\exposid{current_)}@))
17376+
requires @\libconcept{indirectly_swappable}@<iterator_t<@\exposid{Base}@>>;
17377+
\end{itemdecl}
17378+
17379+
\begin{itemdescr}
17380+
\pnum
17381+
\effects
17382+
Equivalent to: \tcode{ranges::iter_swap(x.\exposid{current_}, y.\exposid{current_});}
17383+
\end{itemdescr}
17384+
1709117385
\rSec1[coro.generator]{Range generators}
1709217386

1709317387
\rSec2[coroutine.generator.overview]{Overview}

source/support.tex

+1
Original file line numberDiff line numberDiff line change
@@ -765,6 +765,7 @@
765765
#define @\defnlibxname{cpp_lib_ranges_starts_ends_with}@ 202106L // also in \libheader{algorithm}
766766
#define @\defnlibxname{cpp_lib_ranges_stride}@ 202207L // freestanding, also in \libheader{ranges}
767767
#define @\defnlibxname{cpp_lib_ranges_to_container}@ 202202L // freestanding, also in \libheader{ranges}
768+
#define @\defnlibxname{cpp_lib_ranges_to_input}@ 202502L // freestanding, also in \libheader{ranges}
768769
#define @\defnlibxname{cpp_lib_ranges_zip}@ 202110L
769770
// freestanding, also in \libheader{ranges}, \libheader{tuple}, \libheader{utility}
770771
#define @\defnlibxname{cpp_lib_ratio}@ 202306L // freestanding, also in \libheader{ratio}

0 commit comments

Comments
 (0)