Skip to content

Commit 538983b

Browse files
authored
Merge pull request #154 from steve-downey/rebase_optimize_adaptors
Rebase optimize adaptors paper as published
2 parents a31904e + d208cbb commit 538983b

File tree

7 files changed

+83474
-72922
lines changed

7 files changed

+83474
-72922
lines changed

papers/P2988/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
PYEXECPATH ?= $(shell which python3.12 || which python3.11 || which python3.10)
1+
PYEXECPATH ?= $(shell which python3.13 || which python3.12 || which python3.11 || which python3.10)
22
PYTHON ?= $(shell basename $(PYEXECPATH))
33
VENV := .venv/
44
SOURCE_VENV := . $(VENV)/bin/activate;

papers/P2988/common.tex

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
\usepackage{color} % define colors for strikeouts and underlines
2525
\usepackage{amsmath} % additional math symbols
2626
\usepackage{mathrsfs} % mathscr font
27+
\usepackage{bm}
2728
\usepackage[final]{microtype}
2829
\usepackage[splitindex,original]{imakeidx}
2930
\usepackage{multicol}
@@ -54,6 +55,7 @@
5455
% pdflang={English}]{hyperref}
5556

5657
\usepackage{memhfixc} % fix interactions between hyperref and memoir
58+
\usepackage{environ}
5759
\usepackage{expl3}
5860
\usepackage{xparse}
5961
\usepackage{xstring}
Lines changed: 337 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,337 @@
1+
\documentclass[a4paper,10pt,oneside,openany,final,article]{memoir}
2+
\input{common}
3+
\settocdepth{chapter}
4+
\usepackage{minted}
5+
\usepackage{fontspec}
6+
7+
\begin{document}
8+
\title{Optimize for std::optional in range adaptors}
9+
\author{
10+
Steve Downey \small<\href{mailto:sdowney@gmail.com}{sdowney@gmail.com}> \\
11+
Tomasz Kamiński \small<\href{mailto:tomaszkam@gmail.com}{tomaszkam@gmail.com}> \\
12+
}
13+
\date{} %unused. Type date explicitly below.
14+
\maketitle
15+
16+
\begin{flushright}
17+
\begin{tabular}{ll}
18+
Document \#: & P3913R1 \\
19+
Date: & \today \\
20+
Project: & Programming Language C++ \\
21+
Audience: & LWG
22+
\end{tabular}
23+
\end{flushright}
24+
25+
\begin{abstract}
26+
From PL-011 22.5 [optional] Optimize for std::optional in range adaptors
27+
28+
The range support was added to the optional, making it usable with range adaptors defined in std::views, however, we have not updated the views specification to handle it optimally when possible. This leads to unnecessary template instantiations.
29+
30+
\end{abstract}
31+
32+
\tableofcontents*
33+
34+
\chapter{Motivation}
35+
The range support was added to the optional, making it usable with range adaptors defined in std::views, however, we have not updated the views specification to handle it optimally when possible. This leads to unnecessary template instantiations.
36+
37+
Proposed change:
38+
39+
Add a special case to recognize optional for adaptors:
40+
41+
\begin{itemize}
42+
\item
43+
views::as_const: should return optional or optional<const U\&> (if T is U\&)
44+
\item
45+
views::take(opt, n): empty optional if n is equal to zero, opt otherwise
46+
\item
47+
views::drop(opt, n): empty optional if n greater than zero, opt otherwise
48+
\item
49+
views::reverse: input unchanged
50+
\end{itemize}
51+
52+
\chapter{Design}
53+
54+
55+
\section{views::as_const}
56+
57+
Return \tcode{optional}.
58+
59+
In contrast to \tcode{optional<const T\&>}, \tcode{optional<const T>} is not a view, because it is not assignable. In consequence it should not be returned from \tcode{views::as_const} for \tcode{optional<T>}.
60+
\section{views::take(opt, n)}
61+
62+
Empty \tcode{optional} if \tcode{n} is equal to zero, \tcode{optional} otherwise.
63+
64+
\section{views::drop(opt, n)}
65+
66+
Empty \tcode{optional} if \tcode{n} greater than zero, \tcode{optional} otherwise.
67+
68+
\section{views::reverse}
69+
70+
Input is returned unchanged.
71+
72+
\chapter{Wording}
73+
The proposed changes are relative to the current working draft \cite{N5014}.
74+
75+
76+
\begin{wording}
77+
\rSec1[ranges.general]{General}
78+
79+
\rSec2[range.take]{Take view}
80+
81+
\rSec3[range.take.overview]{Overview}
82+
83+
\pnum
84+
\tcode{take_view} produces a view of the first $N$ elements
85+
from another view, or all the elements if the adapted
86+
view contains fewer than $N$.
87+
88+
\pnum
89+
\indexlibrarymember{take}{views}%
90+
The name \tcode{views::take} denotes a
91+
range adaptor object\iref{range.adaptor.object}.
92+
Let \tcode{E} and \tcode{F} be expressions,
93+
let \tcode{T} be \tcode{remove_cvref_t<decltype((E))>}, and
94+
let \tcode{D} be \tcode{range_difference_t<decltype((E))>}.
95+
If \tcode{decltype((F))} does not model
96+
\tcode{\libconcept{convertible_to}<D>},
97+
\tcode{views::take(E, F)} is ill-formed.
98+
Otherwise, the expression \tcode{views::take(E, F)}
99+
is expression-equivalent to:
100+
101+
\begin{itemize}
102+
\item
103+
If \tcode{T} is a specialization
104+
of \tcode{empty_view}\iref{range.empty.view},
105+
then \tcode{((void)F, \placeholdernc{decay-copy}(E))},
106+
except that the evaluations of \tcode{E} and \tcode{F}
107+
are indeterminately sequenced.
108+
\begin{addedblock}
109+
\item
110+
Otherwise, if \tcode{T} is a specialization of \tcode{optional} and \tcode{T} models \tcode{view}, then \tcode{(static_cast<D>(F) == D() ? ((void)E, T()) : \placeholdernc{decay-copy}(E))}.
111+
\end{addedblock}
112+
\item
113+
Otherwise, if \tcode{T} models
114+
\libconcept{random_access_range} and \libconcept{sized_range}
115+
and is a specialization of
116+
\tcode{span}\iref{views.span},
117+
\tcode{basic_string_view}\iref{string.view}, or
118+
\tcode{subrange}\iref{range.subrange},
119+
then
120+
\tcode{U(ranges::begin(E),
121+
ranges::be\-gin(E) + std::min<D>(ranges::distance(E), F))},
122+
except that \tcode{E} is evaluated only once,
123+
where \tcode{U} is a type determined as follows:
124+
125+
\begin{itemize}
126+
\item if \tcode{T} is a specialization of \tcode{span},
127+
then \tcode{U} is \tcode{span<typename T::element_type>};
128+
\item otherwise, if \tcode{T} is a specialization of \tcode{basic_string_view},
129+
then \tcode{U} is \tcode{T};
130+
\item otherwise, \tcode{T} is a specialization of \tcode{subrange}, and
131+
\tcode{U} is \tcode{subrange<iterator_t<T>>};
132+
\end{itemize}
133+
134+
\item
135+
otherwise, if \tcode{T} is
136+
a specialization of \tcode{iota_view}\iref{range.iota.view}
137+
that models \libconcept{random_access_range} and \libconcept{sized_range},
138+
then
139+
\tcode{iota_view(*ranges::begin(E),
140+
*(ranges::begin(E) + std::\linebreak{}min<D>(ranges::distance(E), F)))},
141+
except that \tcode{E} is evaluated only once.
142+
143+
\item
144+
Otherwise, if \tcode{T} is
145+
a specialization of \tcode{repeat_view}\iref{range.repeat.view}:
146+
\begin{itemize}
147+
\item
148+
if \tcode{T} models \libconcept{sized_range},
149+
then
150+
\begin{codeblock}
151+
views::repeat(*E.@\exposid{value_}@, std::min<D>(ranges::distance(E), F))
152+
\end{codeblock}
153+
except that \tcode{E} is evaluated only once;
154+
\item
155+
otherwise, \tcode{views::repeat(*E.\exposid{value_}, static_cast<D>(F))}.
156+
\end{itemize}
157+
158+
\item
159+
Otherwise, \tcode{take_view(E, F)}.
160+
\end{itemize}
161+
162+
\rSec2[range.drop]{Drop view}
163+
164+
\rSec3[range.drop.overview]{Overview}
165+
166+
\pnum
167+
\tcode{drop_view} produces a view
168+
excluding the first $N$ elements from another view, or
169+
an empty range if the adapted view contains fewer than $N$ elements.
170+
171+
\pnum
172+
\indexlibrarymember{drop}{views}%
173+
The name \tcode{views::drop} denotes
174+
a range adaptor object\iref{range.adaptor.object}.
175+
Let \tcode{E} and \tcode{F} be expressions,
176+
let \tcode{T} be \tcode{remove_cvref_t<decltype((E))>}, and
177+
let \tcode{D} be \tcode{range_difference_t<decltype((E))>}.
178+
If \tcode{decltype((F))} does not model
179+
\tcode{\libconcept{convertible_to}<D>},
180+
\tcode{views::drop(E, F)} is ill-formed.
181+
Otherwise, the expression \tcode{views::drop(E, F)}
182+
is expression-equivalent to:
183+
184+
\begin{itemize}
185+
\item
186+
If \tcode{T} is a specialization of
187+
\tcode{empty_view}\iref{range.empty.view},
188+
then \tcode{((void)F, \placeholdernc{decay-copy}(E))},
189+
except that the evaluations of \tcode{E} and \tcode{F}
190+
are indeterminately sequenced.
191+
\begin{addedblock}
192+
\item
193+
Otherwise, if \tcode{T} is a specialization of \tcode{optional} and \tcode{T} models \tcode{view}, then \tcode{(static_cast<D>(F) == D() ? \placeholdernc{decay-copy}(E) : ((void)E, T()))}.
194+
\end{addedblock}
195+
\item
196+
Otherwise, if \tcode{T} models
197+
\libconcept{random_access_range} and \libconcept{sized_range}
198+
and is
199+
\begin{itemize}
200+
\item a specialization of \tcode{span}\iref{views.span},
201+
\item a specialization of \tcode{basic_string_view}\iref{string.view},
202+
\item a specialization of \tcode{iota_view}\iref{range.iota.view}, or
203+
\item a specialization of \tcode{subrange}\iref{range.subrange}
204+
where \tcode{T::\exposid{StoreSize}} is \tcode{false},
205+
\end{itemize}
206+
then \tcode{U(ranges::begin(E) + std::min<D>(ranges::distance(E), F), ranges::end(E))},
207+
except that \tcode{E} is evaluated only once,
208+
where \tcode{U} is \tcode{span<typename T::element_type>}
209+
if \tcode{T} is a specialization of \tcode{span} and \tcode{T} otherwise.
210+
211+
\item
212+
Otherwise,
213+
if \tcode{T} is
214+
a specialization of \tcode{subrange}
215+
that models \libconcept{random_access_range} and \libconcept{sized_range},
216+
then
217+
\tcode{T(ranges::begin(E) + std::min<D>(ranges::distance(E), F), ranges::\linebreak{}end(E),
218+
\exposid{to-unsigned-like}(ranges::distance(E) -
219+
std::min<D>(ranges::distance(E), F)))},
220+
except that \tcode{E} and \tcode{F} are each evaluated only once.
221+
222+
\item
223+
Otherwise, if \tcode{T} is
224+
a specialization of \tcode{repeat_view}\iref{range.repeat.view}:
225+
\begin{itemize}
226+
\item
227+
if \tcode{T} models \libconcept{sized_range},
228+
then
229+
\begin{codeblock}
230+
views::repeat(*E.@\exposid{value_}@, ranges::distance(E) - std::min<D>(ranges::distance(E), F))
231+
\end{codeblock}
232+
except that \tcode{E} is evaluated only once;
233+
\item
234+
otherwise, \tcode{((void)F, \placeholdernc{decay-copy}(E))},
235+
except that the evaluations of \tcode{E} and \tcode{F} are indeterminately sequenced.
236+
\end{itemize}
237+
238+
\item
239+
Otherwise, \tcode{drop_view(E, F)}.
240+
\end{itemize}
241+
242+
\rSec2[range.as.const]{As const view}
243+
244+
\rSec3[range.as.const.overview]{Overview}
245+
246+
\pnum
247+
\tcode{as_const_view} presents a view of an underlying sequence as constant.
248+
That is, the elements of an \tcode{as_const_view} cannot be modified.
249+
250+
\pnum
251+
The name \tcode{views::as_const} denotes
252+
a range adaptor object\iref{range.adaptor.object}.
253+
Let \tcode{E} be an expression,
254+
let \tcode{T} be \tcode{decltype((E))}, and
255+
let \tcode{U} be \tcode{remove_cvref_t<T>}.
256+
The expression \tcode{views::as_const(E)} is expression-equivalent to:
257+
\begin{itemize}
258+
\item
259+
If \tcode{views::all_t<T>} models \libconcept{constant_range},
260+
then \tcode{views::all(E)}.
261+
\item
262+
Otherwise,
263+
if \tcode{U} denotes \tcode{empty_view<X>}
264+
for some type \tcode{X}, then \tcode{auto(views::empty<const X>)}.
265+
\begin{addedblock}
266+
\item
267+
Otherwise, if \tcode{U} denotes \tcode{optional<X\&>} for some type \tcode{X}, then \tcode{optional<const X\&>(E)}.
268+
\end{addedblock}
269+
\item
270+
Otherwise,
271+
if \tcode{U} denotes \tcode{span<X, Extent>}
272+
for some type \tcode{X} and some extent \tcode{Extent},
273+
then \tcode{span<const X, Extent>(E)}.
274+
\item
275+
Otherwise,
276+
if \tcode{U} denotes \tcode{ref_view<X>} for some type \tcode{X} and
277+
\tcode{const X} models \libconcept{constant_range},
278+
then \tcode{ref_view(static_cast<const X\&>(E.base()))}.
279+
\item
280+
Otherwise,
281+
if \tcode{E} is an lvalue,
282+
\tcode{const U} models \libconcept{constant_range}, and
283+
\tcode{U} does not model \libconcept{view},
284+
then \tcode{ref_view(static_cast<const U\&>(E))}.
285+
\item
286+
Otherwise, \tcode{as_const_view(E)}.
287+
\end{itemize}
288+
289+
\rSec2[range.reverse]{Reverse view}
290+
291+
\rSec3[range.reverse.overview]{Overview}
292+
293+
\pnum
294+
\tcode{reverse_view} takes a bidirectional view and produces
295+
another view that iterates the same elements in reverse order.
296+
297+
\pnum
298+
\indexlibrarymember{reverse}{views}%
299+
The name \tcode{views::reverse} denotes a
300+
range adaptor object\iref{range.adaptor.object}.
301+
Given a subexpression \tcode{E}, the expression
302+
\tcode{views::reverse(E)} is expression-equivalent to:
303+
\begin{itemize}
304+
\item
305+
If the type of \tcode{E} is
306+
a (possibly cv-qualified) specialization of \tcode{reverse_view},
307+
then \tcode{E.base()}.
308+
\begin{addedblock}
309+
\item
310+
Otherwise, if \tcode{E} is specialization of \tcode{optional} and \tcode{E} models \tcode{view}, then \tcode{\placeholdernc{decay-copy}(E)}.
311+
\end{addedblock}
312+
\item
313+
Otherwise, if the type of \tcode{E} is \cv{} \tcode{subrange<reverse_iterator<I>, reverse_iterator<I>, K>}
314+
for some iterator type \tcode{I} and
315+
value \tcode{K} of type \tcode{subrange_kind},
316+
\begin{itemize}
317+
\item
318+
if \tcode{K} is \tcode{subrange_kind::sized}, then
319+
\tcode{subrange<I, I, K>(E.end().base(), E.begin().base(), E.size())};
320+
\item
321+
otherwise, \tcode{subrange<I, I, K>(E.end().base(), E.begin().base())}.
322+
\end{itemize}
323+
However, in either case \tcode{E} is evaluated only once.
324+
\item
325+
Otherwise, \tcode{reverse_view\{E\}}.
326+
\end{itemize}
327+
328+
329+
\end{wording}
330+
331+
332+
\renewcommand{\bibname}{References}
333+
\bibliographystyle{abstract}
334+
\bibliography{wg21,mybiblio}
335+
336+
337+
\end{document}

papers/P2988/stdtex/layout.tex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
%%--------------------------------------------------
1111
%% set header and footer positions and sizes
1212

13-
\setheadfoot{\onelineskip}{4\onelineskip}
13+
\setheadfoot{3\onelineskip}{4\onelineskip}
1414
\setheaderspaces{*}{2\onelineskip}{*}
1515

1616
%%--------------------------------------------------

0 commit comments

Comments
 (0)