-
Notifications
You must be signed in to change notification settings - Fork 22
/
p2415r2.html
964 lines (956 loc) · 88.4 KB
/
p2415r2.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang xml:lang>
<head>
<meta charset="utf-8" />
<meta name="generator" content="mpark/wg21" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />
<meta name="dcterms.date" content="2021-09-24" />
<title>What is a view?</title>
<style>
code{white-space: pre-wrap;}
span.smallcaps{font-variant: small-caps;}
span.underline{text-decoration: underline;}
div.column{display: inline-block; vertical-align: top; width: 50%;}
div.hanging-indent{margin-left: 1.5em; text-indent: -1.5em;}
ul.task-list{list-style: none;}
pre > code.sourceCode { white-space: pre; position: relative; }
pre > code.sourceCode > span { display: inline-block; line-height: 1.25; }
pre > code.sourceCode > span:empty { height: 1.2em; }
code.sourceCode > span { color: inherit; text-decoration: inherit; }
div.sourceCode { margin: 1em 0; }
pre.sourceCode { margin: 0; }
@media screen {
div.sourceCode { overflow: auto; }
}
@media print {
pre > code.sourceCode { white-space: pre-wrap; }
pre > code.sourceCode > span { text-indent: -5em; padding-left: 5em; }
}
pre.numberSource code
{ counter-reset: source-line 0; }
pre.numberSource code > span
{ position: relative; left: -4em; counter-increment: source-line; }
pre.numberSource code > span > a:first-child::before
{ content: counter(source-line);
position: relative; left: -1em; text-align: right; vertical-align: baseline;
border: none; display: inline-block;
-webkit-touch-callout: none; -webkit-user-select: none;
-khtml-user-select: none; -moz-user-select: none;
-ms-user-select: none; user-select: none;
padding: 0 4px; width: 4em;
color: #aaaaaa;
}
pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa; padding-left: 4px; }
div.sourceCode
{ background-color: #f6f8fa; }
@media screen {
pre > code.sourceCode > span > a:first-child::before { text-decoration: underline; }
}
code span. { } /* Normal */
code span.al { color: #ff0000; } /* Alert */
code span.an { } /* Annotation */
code span.at { } /* Attribute */
code span.bn { color: #9f6807; } /* BaseN */
code span.bu { color: #9f6807; } /* BuiltIn */
code span.cf { color: #00607c; } /* ControlFlow */
code span.ch { color: #9f6807; } /* Char */
code span.cn { } /* Constant */
code span.co { color: #008000; font-style: italic; } /* Comment */
code span.cv { color: #008000; font-style: italic; } /* CommentVar */
code span.do { color: #008000; } /* Documentation */
code span.dt { color: #00607c; } /* DataType */
code span.dv { color: #9f6807; } /* DecVal */
code span.er { color: #ff0000; font-weight: bold; } /* Error */
code span.ex { } /* Extension */
code span.fl { color: #9f6807; } /* Float */
code span.fu { } /* Function */
code span.im { } /* Import */
code span.in { color: #008000; } /* Information */
code span.kw { color: #00607c; } /* Keyword */
code span.op { color: #af1915; } /* Operator */
code span.ot { } /* Other */
code span.pp { color: #6f4e37; } /* Preprocessor */
code span.re { } /* RegionMarker */
code span.sc { color: #9f6807; } /* SpecialChar */
code span.ss { color: #9f6807; } /* SpecialString */
code span.st { color: #9f6807; } /* String */
code span.va { } /* Variable */
code span.vs { color: #9f6807; } /* VerbatimString */
code span.wa { color: #008000; font-weight: bold; } /* Warning */
code.diff {color: #898887}
code.diff span.va {color: #006e28}
code.diff span.st {color: #bf0303}
</style>
<style type="text/css">
body {
margin: 5em;
font-family: serif;
hyphens: auto;
line-height: 1.35;
}
div.wrapper {
max-width: 60em;
margin: auto;
}
ul {
list-style-type: none;
padding-left: 2em;
margin-top: -0.2em;
margin-bottom: -0.2em;
}
a {
text-decoration: none;
color: #4183C4;
}
a.hidden_link {
text-decoration: none;
color: inherit;
}
li {
margin-top: 0.6em;
margin-bottom: 0.6em;
}
h1, h2, h3, h4 {
position: relative;
line-height: 1;
}
a.self-link {
position: absolute;
top: 0;
left: calc(-1 * (3.5rem - 26px));
width: calc(3.5rem - 26px);
height: 2em;
text-align: center;
border: none;
transition: opacity .2s;
opacity: .5;
font-family: sans-serif;
font-weight: normal;
font-size: 83%;
}
a.self-link:hover { opacity: 1; }
a.self-link::before { content: "§"; }
ul > li:before {
content: "\2014";
position: absolute;
margin-left: -1.5em;
}
:target { background-color: #C9FBC9; }
:target .codeblock { background-color: #C9FBC9; }
:target ul { background-color: #C9FBC9; }
.abbr_ref { float: right; }
.folded_abbr_ref { float: right; }
:target .folded_abbr_ref { display: none; }
:target .unfolded_abbr_ref { float: right; display: inherit; }
.unfolded_abbr_ref { display: none; }
.secnum { display: inline-block; min-width: 35pt; }
.header-section-number { display: inline-block; min-width: 35pt; }
.annexnum { display: block; }
div.sourceLinkParent {
float: right;
}
a.sourceLink {
position: absolute;
opacity: 0;
margin-left: 10pt;
}
a.sourceLink:hover {
opacity: 1;
}
a.itemDeclLink {
position: absolute;
font-size: 75%;
text-align: right;
width: 5em;
opacity: 0;
}
a.itemDeclLink:hover { opacity: 1; }
span.marginalizedparent {
position: relative;
left: -5em;
}
li span.marginalizedparent { left: -7em; }
li ul > li span.marginalizedparent { left: -9em; }
li ul > li ul > li span.marginalizedparent { left: -11em; }
li ul > li ul > li ul > li span.marginalizedparent { left: -13em; }
div.footnoteNumberParent {
position: relative;
left: -4.7em;
}
a.marginalized {
position: absolute;
font-size: 75%;
text-align: right;
width: 5em;
}
a.enumerated_item_num {
position: relative;
left: -3.5em;
display: inline-block;
margin-right: -3em;
text-align: right;
width: 3em;
}
div.para { margin-bottom: 0.6em; margin-top: 0.6em; text-align: justify; }
div.section { text-align: justify; }
div.sentence { display: inline; }
span.indexparent {
display: inline;
position: relative;
float: right;
right: -1em;
}
a.index {
position: absolute;
display: none;
}
a.index:before { content: "⟵"; }
a.index:target {
display: inline;
}
.indexitems {
margin-left: 2em;
text-indent: -2em;
}
div.itemdescr {
margin-left: 3em;
}
.bnf {
font-family: serif;
margin-left: 40pt;
margin-top: 0.5em;
margin-bottom: 0.5em;
}
.ncbnf {
font-family: serif;
margin-top: 0.5em;
margin-bottom: 0.5em;
margin-left: 40pt;
}
.ncsimplebnf {
font-family: serif;
font-style: italic;
margin-top: 0.5em;
margin-bottom: 0.5em;
margin-left: 40pt;
background: inherit;
}
span.textnormal {
font-style: normal;
font-family: serif;
white-space: normal;
display: inline-block;
}
span.rlap {
display: inline-block;
width: 0px;
}
span.descr { font-style: normal; font-family: serif; }
span.grammarterm { font-style: italic; }
span.term { font-style: italic; }
span.terminal { font-family: monospace; font-style: normal; }
span.nonterminal { font-style: italic; }
span.tcode { font-family: monospace; font-style: normal; }
span.textbf { font-weight: bold; }
span.textsc { font-variant: small-caps; }
a.nontermdef { font-style: italic; font-family: serif; }
span.emph { font-style: italic; }
span.techterm { font-style: italic; }
span.mathit { font-style: italic; }
span.mathsf { font-family: sans-serif; }
span.mathrm { font-family: serif; font-style: normal; }
span.textrm { font-family: serif; }
span.textsl { font-style: italic; }
span.mathtt { font-family: monospace; font-style: normal; }
span.mbox { font-family: serif; font-style: normal; }
span.ungap { display: inline-block; width: 2pt; }
span.textit { font-style: italic; }
span.texttt { font-family: monospace; }
span.tcode_in_codeblock { font-family: monospace; font-style: normal; }
span.phantom { color: white; }
span.math { font-style: normal; }
span.mathblock {
display: block;
margin-left: auto;
margin-right: auto;
margin-top: 1.2em;
margin-bottom: 1.2em;
text-align: center;
}
span.mathalpha {
font-style: italic;
}
span.synopsis {
font-weight: bold;
margin-top: 0.5em;
display: block;
}
span.definition {
font-weight: bold;
display: block;
}
.codeblock {
margin-left: 1.2em;
line-height: 127%;
}
.outputblock {
margin-left: 1.2em;
line-height: 127%;
}
div.itemdecl {
margin-top: 2ex;
}
code.itemdeclcode {
white-space: pre;
display: block;
}
span.textsuperscript {
vertical-align: super;
font-size: smaller;
line-height: 0;
}
.footnotenum { vertical-align: super; font-size: smaller; line-height: 0; }
.footnote {
font-size: small;
margin-left: 2em;
margin-right: 2em;
margin-top: 0.6em;
margin-bottom: 0.6em;
}
div.minipage {
display: inline-block;
margin-right: 3em;
}
div.numberedTable {
text-align: center;
margin: 2em;
}
div.figure {
text-align: center;
margin: 2em;
}
table {
border: 1px solid black;
border-collapse: collapse;
margin-left: auto;
margin-right: auto;
margin-top: 0.8em;
text-align: left;
hyphens: none;
}
td, th {
padding-left: 1em;
padding-right: 1em;
vertical-align: top;
}
td.empty {
padding: 0px;
padding-left: 1px;
}
td.left {
text-align: left;
}
td.right {
text-align: right;
}
td.center {
text-align: center;
}
td.justify {
text-align: justify;
}
td.border {
border-left: 1px solid black;
}
tr.rowsep, td.cline {
border-top: 1px solid black;
}
tr.even, tr.odd {
border-bottom: 1px solid black;
}
tr.capsep {
border-top: 3px solid black;
border-top-style: double;
}
tr.header {
border-bottom: 3px solid black;
border-bottom-style: double;
}
th {
border-bottom: 1px solid black;
}
span.centry {
font-weight: bold;
}
div.table {
display: block;
margin-left: auto;
margin-right: auto;
text-align: center;
width: 90%;
}
span.indented {
display: block;
margin-left: 2em;
margin-bottom: 1em;
margin-top: 1em;
}
ol.enumeratea { list-style-type: none; background: inherit; }
ol.enumerate { list-style-type: none; background: inherit; }
code.sourceCode > span { display: inline; }
</style>
<style type="text/css">a {
color : #4183C4;
text-decoration: underline;
}
a.marginalized {
text-decoration: none;
}
a.self-link {
text-decoration: none;
}
h1#toctitle {
border-bottom: 1px solid #cccccc;
}
#TOC li {
margin-top: 1px;
margin-bottom: 1px;
}
#TOC ul>li:before { display: none; }
h3.subtitle { margin-top: -15px; }
h1:target { background-color: transparent; }
h2:target { background-color: transparent; }
h3:target { background-color: transparent; }
h4:target { background-color: transparent; }
h5:target { background-color: transparent; }
h6:target { background-color: transparent; }
code span.co { font-family: monospace; }
table tr {
background-color: white;
}
table tr:nth-child(2n) {
background-color: #f6f8fa;
}
#title-block-header > table tr:nth-child(2n) {
background-color: white;
}
td > div.sourceCode {
background-color: inherit;
}
table {
border-collapse: collapse;
}
table td, table th {
border: 1px solid #cccccc;
}
table th {
border-bottom: 1px solid black;
text-align: center;
}
table tr:first-child th {
border-top: 0;
}
table tr:last-child td {
border-bottom: 0;
}
table tr td:first-child,
table tr th:first-child {
border-left: 0;
}
table tr td:last-child,
table tr th:last-child {
border-right: 0;
}
table tbody tr:first-child td {
border-top: 1px solid black;
}
#title-block-header td { border: 0; }
@media all {
body {
margin: 2em;
}
}
@media screen and (min-width: 480px) {
body {
margin: 5em;
}
}
#refs code{padding-left: 0px; text-indent: 0px;}
:root {
--diff-ins: #e6ffed;
--diff-strongins: #acf2bd;
--diff-del: #ffdddd;
--diff-strongdel: #ff8888;
}
span.diffins {
background-color: var(--diff-strongins);
}
span.diffdel {
background-color: var(--diff-strongdel);
}
div.rm { text-decoration: line-through; }
div.rm code.sourceCode { text-decoration: line-through; }
div.addu, span.addu {
color: #006e28;
background-color: var(--diff-ins);
}
div.rm pre, div.add pre { background-color: #f6f8fa; }
div.addu pre { background-color: var(--diff-ins); }
div.add, div.add pre { background-color: var(--diff-ins); }
div.addu blockquote {
border-left: 4px solid #00a000;
padding: 0 15px;
color: #006e28;
text-decoration: none;
}
div.addu blockquote code.sourceCode { text-decoration: none; }
div.addu blockquote pre { text-decoration: none; }
div.addu blockquote pre code { text-decoration: none; }
div.quote {
border-left: 7px solid #ccc;
background: #f9f9f9;
margin: 1.5em 10px;
padding-left: 20px;
}
code.diff span.va { color: #000000; background-color: var(--diff-ins); }
code.diff span.st { color: #000000; background-color: var(--diff-del); }
</style>
<link href="data:image/x-icon;base64,AAABAAIAEBAAAAEAIABoBAAAJgAAACAgAAABACAAqBAAAI4EAAAoAAAAEAAAACAAAAABACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////AIJEAACCRAAAgkQAAIJEAACCRAAAgkQAVoJEAN6CRADegkQAWIJEAACCRAAAgkQAAIJEAACCRAAA////AP///wCCRAAAgkQAAIJEAACCRAAsgkQAvoJEAP+CRAD/gkQA/4JEAP+CRADAgkQALoJEAACCRAAAgkQAAP///wD///8AgkQAAIJEABSCRACSgkQA/IJEAP99PQD/dzMA/3czAP99PQD/gkQA/4JEAPyCRACUgkQAFIJEAAD///8A////AHw+AFiBQwDqgkQA/4BBAP9/PxP/uZd6/9rJtf/bybX/upd7/39AFP+AQQD/gkQA/4FDAOqAQgBc////AP///wDKklv4jlEa/3o7AP+PWC//8+3o///////////////////////z7un/kFox/35AAP+GRwD/mVYA+v///wD///8A0Zpk+NmibP+0d0T/8evj///////+/fv/1sKz/9bCs//9/fr//////+/m2/+NRwL/nloA/5xYAPj///8A////ANKaZPjRmGH/5cKh////////////k149/3UwAP91MQD/lmQ//86rhv+USg3/m1YA/5hSAP+bVgD4////AP///wDSmmT4zpJY/+/bx///////8+TV/8mLT/+TVx//gkIA/5lVAP+VTAD/x6B//7aEVv/JpH7/s39J+P///wD///8A0ppk+M6SWP/u2sf///////Pj1f/Nj1T/2KFs/8mOUv+eWhD/lEsA/8aee/+0glT/x6F7/7J8Rvj///8A////ANKaZPjRmGH/48Cf///////+/v7/2qt//82PVP/OkFX/37KJ/86siv+USg7/mVQA/5hRAP+bVgD4////AP///wDSmmT40ppk/9CVXP/69O////////7+/v/x4M//8d/P//7+/f//////9u7n/6tnJf+XUgD/nFgA+P///wD///8A0ppk+NKaZP/RmWL/1qNy//r07///////////////////////+vXw/9akdP/Wnmn/y5FY/6JfFvj///8A////ANKaZFTSmmTo0ppk/9GYYv/Ql1//5cWm//Hg0P/x4ND/5cWm/9GXYP/RmGH/0ppk/9KaZOjVnmpY////AP///wDSmmQA0ppkEtKaZI7SmmT60ppk/9CWX//OkVb/zpFW/9CWX//SmmT/0ppk/NKaZJDSmmQS0ppkAP///wD///8A0ppkANKaZADSmmQA0ppkKtKaZLrSmmT/0ppk/9KaZP/SmmT/0ppkvNKaZCrSmmQA0ppkANKaZAD///8A////ANKaZADSmmQA0ppkANKaZADSmmQA0ppkUtKaZNzSmmTc0ppkVNKaZADSmmQA0ppkANKaZADSmmQA////AP5/AAD4HwAA4AcAAMADAACAAQAAgAEAAIABAACAAQAAgAEAAIABAACAAQAAgAEAAMADAADgBwAA+B8AAP5/AAAoAAAAIAAAAEAAAAABACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////AP///wCCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAAyCRACMgkQA6oJEAOqCRACQgkQAEIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAA////AP///wD///8A////AIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRABigkQA5oJEAP+CRAD/gkQA/4JEAP+CRADqgkQAZoJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAAD///8A////AP///wD///8AgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAA4gkQAwoJEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQAxIJEADyCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAAgkQAAP///wD///8A////AP///wCCRAAAgkQAAIJEAACCRAAAgkQAAIJEAACCRAAWgkQAmIJEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAJyCRAAYgkQAAIJEAACCRAAAgkQAAIJEAACCRAAA////AP///wD///8A////AIJEAACCRAAAgkQAAIJEAACCRAAAgkQAdIJEAPCCRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAP+CRAD/gkQA/4JEAPSCRAB4gkQAAIJEAACCRAAAgkQAAIJEAAD///8A////AP///wD///8AgkQAAIJEAACCRAAAgkQASoJEANKCRAD/gkQA/4JEAP+CRAD/g0YA/39AAP9zLgD/bSQA/2shAP9rIQD/bSQA/3MuAP9/PwD/g0YA/4JEAP+CRAD/gkQA/4JEAP+CRADUgkQAToJEAACCRAAAgkQAAP///wD///8A////AP///wB+PwAAgkUAIoJEAKiCRAD/gkQA/4JEAP+CRAD/hEcA/4BBAP9sIwD/dTAA/5RfKv+viF7/vp56/76ee/+wiF7/lWAr/3YxAP9sIwD/f0AA/4RHAP+CRAD/gkQA/4JEAP+CRAD/gkQArIJEACaBQwAA////AP///wD///8A////AIBCAEBzNAD6f0EA/4NFAP+CRAD/gkQA/4VIAP92MwD/bSUA/6N1Tv/ezsL/////////////////////////////////38/D/6V3Uv9uJgD/dTEA/4VJAP+CRAD/gkQA/4JEAP+BQwD/fUAA/4FDAEj///8A////AP///wD///8AzJRd5qBlKf91NgD/dDUA/4JEAP+FSQD/cy4A/3YyAP/PuKP//////////////////////////////////////////////////////9K7qP94NQD/ciwA/4VJAP+CRAD/fkEA/35BAP+LSwD/mlYA6v///wD///8A////AP///wDdpnL/4qx3/8KJUv+PUhf/cTMA/3AsAP90LgD/4dK+/////////////////////////////////////////////////////////////////+TYxf91MAD/dTIA/31CAP+GRwD/llQA/6FcAP+gWwD8////AP///wD///8A////ANGZY/LSm2X/4ap3/92mcP+wdT3/byQA/8mwj////////////////////////////////////////////////////////////////////////////+LYxv9zLgP/jUoA/59bAP+hXAD/nFgA/5xYAPL///8A////AP///wD///8A0ppk8tKaZP/RmWL/1p9q/9ubXv/XqXj////////////////////////////7+fD/vZyG/6BxS/+gcUr/vJuE//r37f//////////////////////3MOr/5dQBf+dVQD/nVkA/5xYAP+cWAD/nFgA8v///wD///8A////AP///wDSmmTy0ppk/9KaZP/SmWP/yohJ//jo2P//////////////////////4NTG/4JDFf9lGAD/bSQA/20kAP9kGAD/fz8S/+Xb0f//////5NG9/6txN/+LOgD/m1QA/51aAP+cWAD/m1cA/5xYAP+cWADy////AP///wD///8A////ANKaZPLSmmT/0ppk/8+TWf/Unmv//v37//////////////////////+TWRr/VwsA/35AAP+ERgD/g0UA/4JGAP9lHgD/kFga/8KXX/+TRwD/jT4A/49CAP+VTQD/n10A/5xYAP+OQQD/lk4A/55cAPL///8A////AP///wD///8A0ppk8tKaZP/SmmT/y4tO/92yiP//////////////////////8NnE/8eCQP+rcTT/ez0A/3IyAP98PgD/gEMA/5FSAP+USwD/jj8A/5lUAP+JNwD/yqV2/694Mf+HNQD/jkAA/82rf/+laBj/jT4A8v///wD///8A////AP///wDSmmTy0ppk/9KaZP/LiUr/4byY///////////////////////gupX/0I5P/+Wuev/Lklz/l1sj/308AP+QSwD/ol0A/59aAP+aVQD/k0oA/8yoh///////+fXv/6pwO//Lp3v///////Pr4f+oay7y////AP///wD///8A////ANKaZPLSmmT/0ppk/8uJSv/hvJj//////////////////////+G7l//Jhkb/0ppk/96nc//fqXX/x4xO/6dkFP+QSQD/llEA/5xXAP+USgD/yaOA///////38uv/qG05/8ijdv//////8efb/6ZpLPL///8A////AP///wD///8A0ppk8tKaZP/SmmT/zIxO/9yxh///////////////////////7dbA/8iEQf/Sm2X/0Zlj/9ScZv/eqHf/2KJv/7yAQf+XTgD/iToA/5lSAP+JNgD/yKFv/611LP+HNQD/jT8A/8qmeP+kZRT/jT4A8v///wD///8A////AP///wDSmmTy0ppk/9KaZP/Pk1n/1J5q//78+//////////////////+/fv/1aFv/8iEQv/Tm2b/0ppl/9GZY//Wn2z/1pZc/9eldf/Bl2b/kUcA/4w9AP+OQAD/lUwA/59eAP+cWQD/jT8A/5ZOAP+eXADy////AP///wD///8A////ANKaZPLSmmT/0ppk/9KZY//KiEn/8d/P///////////////////////47+f/05tm/8iCP//KiEj/yohJ/8eCP//RmGH//vfy///////n1sP/rXQ7/4k4AP+TTAD/nVoA/5xYAP+cVwD/nFgA/5xYAPL///8A////AP///wD///8A0ppk8tKaZP/SmmT/0ptl/8uLTf/aq37////////////////////////////+/fz/6c2y/961jv/etY7/6Myx//78+v//////////////////////3MWv/5xXD/+ORAD/mFQA/51ZAP+cWAD/nFgA8v///wD///8A////AP///wDSmmTy0ppk/9KaZP/SmmT/0ppk/8mFRP/s1b//////////////////////////////////////////////////////////////////////////////+PD/0JFU/7NzMv+WUQD/kUsA/5tXAP+dWQDy////AP///wD///8A////ANKaZP/SmmT/0ppk/9KaZP/Sm2X/z5NZ/8yMT//z5NX/////////////////////////////////////////////////////////////////9Ofa/8yNUP/UmGH/36p5/8yTWv+qaSD/kksA/5ROAPz///8A////AP///wD///8A0ppk5NKaZP/SmmT/0ppk/9KaZP/TnGf/zY9T/82OUv/t1sD//////////////////////////////////////////////////////+7Yw//OkFX/zI5R/9OcZ//SmmP/26V0/9ymdf/BhUf/ol8R6P///wD///8A////AP///wDSmmQ80ppk9tKaZP/SmmT/0ppk/9KaZP/TnGj/zpFW/8qJSv/dson/8uHS//////////////////////////////////Lj0//etIv/y4lL/86QVf/TnGj/0ppk/9KaZP/RmWP/05xn/9ymdfjUnWdC////AP///wD///8A////ANKaZADSmmQc0ppkotKaZP/SmmT/0ppk/9KaZP/Tm2b/0Zli/8qJSf/NjlH/16Z3/+G8mP/myKr/5siq/+G8mP/Xp3f/zY5S/8qISf/RmGH/05tm/9KaZP/SmmT/0ppk/9KaZP/SmmSm0pljINWdaQD///8A////AP///wD///8A0ppkANKaZADSmmQA0ppkQtKaZMrSmmT/0ppk/9KaZP/SmmT/0ptl/9GYYf/Nj1P/y4lL/8qISP/KiEj/y4lK/82PU//RmGH/0ptl/9KaZP/SmmT/0ppk/9KaZP/SmmTO0ppkRtKaZADSmmQA0ppkAP///wD///8A////AP///wDSmmQA0ppkANKaZADSmmQA0ppkANKaZGzSmmTu0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmTw0ppkcNKaZADSmmQA0ppkANKaZADSmmQA////AP///wD///8A////ANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZBLSmmSQ0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppklNKaZBTSmmQA0ppkANKaZADSmmQA0ppkANKaZAD///8A////AP///wD///8A0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQy0ppkutKaZP/SmmT/0ppk/9KaZP/SmmT/0ppk/9KaZP/SmmT/0ppkvtKaZDbSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkAP///wD///8A////AP///wDSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkXNKaZODSmmT/0ppk/9KaZP/SmmT/0ppk5NKaZGDSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA////AP///wD///8A////ANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkBtKaZIbSmmTo0ppk6tKaZIrSmmQK0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZADSmmQA0ppkANKaZAD///8A////AP/8P///+B///+AH//+AAf//AAD//AAAP/AAAA/gAAAHwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA+AAAAfwAAAP/AAAP/8AAP//gAH//+AH///4H////D//" rel="icon" />
<!--[if lt IE 9]>
<script src="//cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv-printshiv.min.js"></script>
<![endif]-->
</head>
<body>
<div class="wrapper">
<header id="title-block-header">
<h1 class="title" style="text-align:center">What is a <code class="sourceCode cpp">view</code>?</h1>
<table style="border:none;float:right">
<tr>
<td>Document #:</td>
<td>P2415R2</td>
</tr>
<tr>
<td>Date:</td>
<td>2021-09-24</td>
</tr>
<tr>
<td style="vertical-align:top">Project:</td>
<td>Programming Language C++</td>
</tr>
<tr>
<td style="vertical-align:top">Audience:</td>
<td>
LEWG<br>
</td>
</tr>
<tr>
<td style="vertical-align:top">Reply-to:</td>
<td>
Barry Revzin<br><<a href="mailto:[email protected]" class="email">[email protected]</a>><br>
Tim Song<br><<a href="mailto:[email protected]" class="email">[email protected]</a>><br>
</td>
</tr>
</table>
</header>
<div style="clear:both">
<div id="TOC" role="doc-toc">
<h1 id="toctitle">Contents</h1>
<ul>
<li><a href="#revision-history"><span class="toc-section-number">1</span> Revision History<span></span></a></li>
<li><a href="#introduction"><span class="toc-section-number">2</span> Introduction<span></span></a></li>
<li><a href="#the-need-for-cheap-copies"><span class="toc-section-number">3</span> The need for cheap copies<span></span></a></li>
<li><a href="#refining-the-view-requirements"><span class="toc-section-number">4</span> Refining the view requirements<span></span></a></li>
<li><a href="#what-is-a-view"><span class="toc-section-number">5</span> What is a <code class="sourceCode cpp">view</code>?<span></span></a></li>
<li><a href="#implementation-experience"><span class="toc-section-number">6</span> Implementation Experience<span></span></a></li>
<li><a href="#proposed-wording"><span class="toc-section-number">7</span> Proposed Wording<span></span></a></li>
<li><a href="#bibliography"><span class="toc-section-number">8</span> References<span></span></a></li>
</ul>
</div>
<h1 data-number="1" style="border-bottom:1px solid #cccccc" id="revision-history"><span class="header-section-number">1</span> Revision History<a href="#revision-history" class="self-link"></a></h1>
<p>Since <span class="citation" data-cites="P2415R0">[<a href="#ref-P2415R0" role="doc-biblioref">P2415R0</a>]</span>, added wording.</p>
<h1 data-number="2" style="border-bottom:1px solid #cccccc" id="introduction"><span class="header-section-number">2</span> Introduction<a href="#introduction" class="self-link"></a></h1>
<p>C++20 Ranges introduced two main concepts for dealing with ranges: <code class="sourceCode cpp">range</code> and <code class="sourceCode cpp">view</code>. These notions were introduced way back in the original paper, “Ranges for the Standard Library” <span class="citation" data-cites="N4128">[<a href="#ref-N4128" role="doc-biblioref">N4128</a>]</span> (though under different names than what we have now - what we now know as <code class="sourceCode cpp">range</code> and <code class="sourceCode cpp">view</code> were originally specified as <code class="sourceCode cpp">Iterable</code> and <code class="sourceCode cpp">Range</code><a href="#fn1" class="footnote-ref" id="fnref1" role="doc-noteref"><sup>1</sup></a>):</p>
<div class="quote">
<p>[A Range] type is one for which we can call <code class="sourceCode cpp">begin<span class="op">()</span></code> and <code class="sourceCode cpp">end<span class="op">()</span></code> to yield an iterator/sentinel pair. (Sentinels are described below.) The [Range] concept says nothing about the type’s constructibility or assignability. Range-based standard algorithms are constrained using the [Range] concept.</p>
<p>[…]</p>
<p>The [View] concept is modeled by lightweight objects that denote a range of elements they do not own. A pair of iterators can be a model of [View], whereas a <code class="sourceCode cpp">vector</code> is not. [View], as opposed to [Range], requires copyability and assignability. Copying and assignment are required to execute in constant time; that is, the cost of these operations is not proportional to the number of elements in the Range.</p>
<p>The [View] concept refines the [Range] concept by additionally requiring following valid expressions for an object <code class="sourceCode cpp">o</code> of type <code class="sourceCode cpp">O</code>:</p>
<div class="sourceCode" id="cb1"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb1-1"><a href="#cb1-1"></a><span class="co">// Constructible:</span></span>
<span id="cb1-2"><a href="#cb1-2"></a><span class="kw">auto</span> o1 <span class="op">=</span> o;</span>
<span id="cb1-3"><a href="#cb1-3"></a><span class="kw">auto</span> o2 <span class="op">=</span> std<span class="op">::</span>move<span class="op">(</span>o<span class="op">)</span>;</span>
<span id="cb1-4"><a href="#cb1-4"></a>O o3; <span class="co">// default-constructed, singular</span></span>
<span id="cb1-5"><a href="#cb1-5"></a><span class="co">// Assignable:</span></span>
<span id="cb1-6"><a href="#cb1-6"></a>o2 <span class="op">=</span> o1;</span>
<span id="cb1-7"><a href="#cb1-7"></a>o2 <span class="op">=</span> std<span class="op">::</span>move<span class="op">(</span>o1<span class="op">)</span>;</span>
<span id="cb1-8"><a href="#cb1-8"></a><span class="co">// Destructible</span></span>
<span id="cb1-9"><a href="#cb1-9"></a>o<span class="op">.~</span>O<span class="op">()</span>;</span></code></pre></div>
<p>The [View] concept exists to give the range adaptors consistent and predictable semantics, and memory and performance characteristics. Since adaptors allow the composition of range objects, those objects must be efficiently copyable (or at least movable). The result of adapting a [View] is a [View]. The result of adapting a container is also a [View]; the container – or any [Range] that is not already a [View] – is first converted to a [View] automatically by taking the container’s <code class="sourceCode cpp">begin</code> and <code class="sourceCode cpp">end</code>.</p>
</div>
<p>The paper really stresses two points throughout:</p>
<ul>
<li>views are lightweight objects that refer to elements they do not own<a href="#fn2" class="footnote-ref" id="fnref2" role="doc-noteref"><sup>2</sup></a></li>
<li>views are O(1) copyable and assignable</li>
</ul>
<p>This design got muddled a bit when views ceased to require copyability, as a result of “Move-only Views” <span class="citation" data-cites="P1456R1">[<a href="#ref-P1456R1" role="doc-biblioref">P1456R1</a>]</span>. As the title suggests, this paper relaxed the requirement that views be copyable, and got us to the set of requirements we have now in <span>24.4.4 <a href="https://wg21.link/range.view">[range.view]</a></span>:</p>
<ul>
<li>views are O(1) move constructible, move assignable, and destructible</li>
<li>views are either O(1) copy constructible/assignable or not copy constructible/assignable</li>
</ul>
<p>But somehow absent from the discussion is: why do we care about views and range adaptors being cheap to copy and assign and destroy? This isn’t just idle navel-gazing either, <span class="citation" data-cites="LWG3452">[<a href="#ref-LWG3452" role="doc-biblioref">LWG3452</a>]</span> points out that requiring strict O(1) destruction has implications for whether <code class="sourceCode cpp">std<span class="op">::</span>generator</code> <span class="citation" data-cites="P2168R3">[<a href="#ref-P2168R3" role="doc-biblioref">P2168R3</a>]</span> can be a <code class="sourceCode cpp">view</code>. What can go wrong in a program that annotates a range as being a <code class="sourceCode cpp">view</code> despite not meeting these requirements?</p>
<p>The goal of this paper is to provide good answers to these questions.</p>
<h1 data-number="3" style="border-bottom:1px solid #cccccc" id="the-need-for-cheap-copies"><span class="header-section-number">3</span> The need for cheap copies<a href="#the-need-for-cheap-copies" class="self-link"></a></h1>
<p>N4128 asked the following question:</p>
<div class="quote">
<div class="sourceCode" id="cb2"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb2-1"><a href="#cb2-1"></a><span class="kw">auto</span> rng <span class="op">=</span> v <span class="op">|</span> view<span class="op">::</span>reverse;</span></code></pre></div>
<p>This creates a view of <code class="sourceCode cpp">v</code> that iterates in reverse order. Now: is <code class="sourceCode cpp">rng</code> copyable, and if so, how expensive is the copy operation?</p>
</div>
<p>Why is this question important? The initial thought to <code class="sourceCode cpp">rng</code> itself being cheap to copy might be that we need this requirement because we write algorithms that take views by value:</p>
<blockquote>
<div class="sourceCode" id="cb3"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb3-1"><a href="#cb3-1"></a><span class="kw">template</span> <span class="op"><</span>input_view V<span class="op">></span></span>
<span id="cb3-2"><a href="#cb3-2"></a><span class="dt">void</span> some_algo<span class="op">(</span>V v<span class="op">)</span>;</span></code></pre></div>
</blockquote>
<p>We could have gone that route (and we definitely do encourage people to take <em>specific</em> views by value - such as <code class="sourceCode cpp">span</code> and <code class="sourceCode cpp">string_view</code>), but that would affect the usability of range-based algorithms. You could not write <code class="sourceCode cpp">ranges<span class="op">::</span>sort<span class="op">(</span>v<span class="op">)</span></code> on a <code class="sourceCode cpp">vector<span class="op"><</span>T<span class="op">></span></code>, since that is not a view - you would have to write <code class="sourceCode cpp">ranges<span class="op">::</span>sort<span class="op">(</span>views<span class="op">::</span>all<span class="op">(</span>v<span class="op">))</span></code> or perhaps something like <code class="sourceCode cpp">ranges<span class="op">::</span>sort<span class="op">(</span>v<span class="op">.</span>all<span class="op">())</span></code> or <code class="sourceCode cpp">ranges<span class="op">::</span>sort<span class="op">(</span>v<span class="op">.</span>view<span class="op">())</span></code>. Either way, we very much want range-based algorithms to be able to operate on, well, ranges, so these are always written instead to take ranges by forwarding reference:</p>
<blockquote>
<div class="sourceCode" id="cb4"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb4-1"><a href="#cb4-1"></a><span class="kw">template</span> <span class="op"><</span>input_range R<span class="op">></span></span>
<span id="cb4-2"><a href="#cb4-2"></a><span class="dt">void</span> some_algo<span class="op">(</span>R<span class="op">&&</span> r<span class="op">)</span>;</span></code></pre></div>
</blockquote>
<p>At best, we write algorithms that do require views and it’s those algorithms that themselves construct the views that they need - but their API surface still takes ranges (specifically, <code class="sourceCode cpp">viewable_range</code>s <span>24.4.5 <a href="https://wg21.link/range.refinements">[range.refinements]</a></span>) by forwarding reference.</p>
<p>If we don’t care about views being cheap to copy because of the desire to write algorithms that take them by value, then why do we care about views being cheap to copy?</p>
<p>Because we very much care about views being cheap to <em>construct</em>.</p>
<p>Let’s go back to this example:</p>
<blockquote>
<div class="sourceCode" id="cb5"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb5-1"><a href="#cb5-1"></a><span class="kw">auto</span> rng <span class="op">=</span> v <span class="op">|</span> views<span class="op">::</span>reverse;</span></code></pre></div>
</blockquote>
<p>This is intended to be a lazy range adaptor - constructing <code class="sourceCode cpp">rng</code> here isn’t intended to do any work, it’s just preparing to do work in the future. It’s important for this to be “cheap” - in the sense that this should absolutely not end up copying all the elements of <code class="sourceCode cpp">v</code>, or really doing any operation on the elements of <code class="sourceCode cpp">v</code>. This extends to all layering of range adaptors:</p>
<blockquote>
<div class="sourceCode" id="cb6"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb6-1"><a href="#cb6-1"></a><span class="kw">auto</span> rng <span class="op">=</span> v <span class="op">|</span> views<span class="op">::</span>some</span>
<span id="cb6-2"><a href="#cb6-2"></a> <span class="op">|</span> views<span class="op">::</span>operations</span>
<span id="cb6-3"><a href="#cb6-3"></a> <span class="op">|</span> views<span class="op">::</span>here;</span></code></pre></div>
</blockquote>
<p>If constructing each of these range adaptors in turn required touching all the elements of <code class="sourceCode cpp">v</code>, this would be a horribly expensive construct - and we haven’t even done anything yet! This is why we need views to be cheap to copy - range adaptors <em>are</em> the algorithms for views, and we need to be able to pass views cheaply to those.</p>
<h1 data-number="4" style="border-bottom:1px solid #cccccc" id="refining-the-view-requirements"><span class="header-section-number">4</span> Refining the view requirements<a href="#refining-the-view-requirements" class="self-link"></a></h1>
<p>Currently, in order for a type <code class="sourceCode cpp">T</code> to model <code class="sourceCode cpp">view</code>, it needs to have O(1) move construction, move assignment, and destruction. If <code class="sourceCode cpp">T</code> is copyable, the copy operations also need to be O(1). What happens if a type <code class="sourceCode cpp">T</code> satisfies <code class="sourceCode cpp">view</code> (whether by it inheriting from <code class="sourceCode cpp">view_base</code>, inheriting from <code class="sourceCode cpp">view_interface<span class="op"><</span>T<span class="op">></span></code>, or simply specializing <code class="sourceCode cpp">enable_view<span class="op"><</span>T<span class="op">></span></code> to be <code class="sourceCode cpp"><span class="kw">true</span></code>), yet does not actually satisfy the O(1) semantics I just laid out?</p>
<p>Consider:</p>
<blockquote>
<div class="sourceCode" id="cb7"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb7-1"><a href="#cb7-1"></a><span class="kw">struct</span> bad_view <span class="op">:</span> view_interface<span class="op"><</span>bad_view<span class="op">></span> <span class="op">{</span></span>
<span id="cb7-2"><a href="#cb7-2"></a> std<span class="op">::</span>vector<span class="op"><</span><span class="dt">int</span><span class="op">></span> v;</span>
<span id="cb7-3"><a href="#cb7-3"></a> </span>
<span id="cb7-4"><a href="#cb7-4"></a> bad_view<span class="op">(</span>std<span class="op">::</span>vector<span class="op"><</span><span class="dt">int</span><span class="op">></span> v<span class="op">)</span> <span class="op">:</span> v<span class="op">(</span>std<span class="op">::</span>move<span class="op">(</span>v<span class="op">))</span> <span class="op">{</span> <span class="op">}</span></span>
<span id="cb7-5"><a href="#cb7-5"></a> </span>
<span id="cb7-6"><a href="#cb7-6"></a> std<span class="op">::</span>vector<span class="op"><</span><span class="dt">int</span><span class="op">>::</span>iterator begin<span class="op">()</span> <span class="op">{</span> <span class="cf">return</span> v<span class="op">.</span>begin<span class="op">()</span>; <span class="op">}</span></span>
<span id="cb7-7"><a href="#cb7-7"></a> std<span class="op">::</span>vector<span class="op"><</span><span class="dt">int</span><span class="op">>::</span>iterator end<span class="op">()</span> <span class="op">{</span> <span class="cf">return</span> v<span class="op">.</span>end<span class="op">()</span>; <span class="op">}</span></span>
<span id="cb7-8"><a href="#cb7-8"></a><span class="op">}</span>;</span>
<span id="cb7-9"><a href="#cb7-9"></a></span>
<span id="cb7-10"><a href="#cb7-10"></a>std<span class="op">::</span>vector<span class="op"><</span><span class="dt">int</span><span class="op">></span> get_ints<span class="op">()</span>;</span>
<span id="cb7-11"><a href="#cb7-11"></a></span>
<span id="cb7-12"><a href="#cb7-12"></a><span class="kw">auto</span> rng <span class="op">=</span> bad_view<span class="op">(</span>get_ints<span class="op">())</span> <span class="op">|</span> views<span class="op">::</span>enumerate;</span>
<span id="cb7-13"><a href="#cb7-13"></a><span class="cf">for</span> <span class="op">(</span><span class="kw">auto</span> <span class="kw">const</span><span class="op">&</span> <span class="op">[</span>idx, i<span class="op">]</span> <span class="op">:</span> rng<span class="op">)</span> <span class="op">{</span></span>
<span id="cb7-14"><a href="#cb7-14"></a> std<span class="op">::</span>print<span class="op">(</span><span class="st">"{}. {}</span><span class="sc">\n</span><span class="st">"</span>, idx, i<span class="op">)</span>;</span>
<span id="cb7-15"><a href="#cb7-15"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
<p><code class="sourceCode cpp">bad_view</code> is, as the name might suggest, a bad view. It is O(1) move constructible and move assignable, but it is not O(1) destructible. It is copyable, but not O(1) copyable (though nothing in this program tries to copy a <code class="sourceCode cpp">bad_view</code> - but if it did, that would be expensive!). As a result, this program is violating <span>16.4.5.11 <a href="https://wg21.link/res.on.requirements">[res.on.requirements]</a></span>/2:</p>
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_1" id="pnum_1">2</a></span> If the validity or meaning of a program depends on whether a sequence of template arguments models a concept, and the concept is satisfied but not modeled, the program is ill-formed, no diagnostic required.</p>
</blockquote>
<p>Ill-formed, no diagnostic required! That is a harsh ruling for this program!</p>
<p>But what actually goes wrong if a program-defined <code class="sourceCode cpp">view</code> ends up violating the semantic requirements of a <code class="sourceCode cpp">view</code>? The goal of a <code class="sourceCode cpp">view</code> is to enable cheap construction of range adaptors. If that construction isn’t as cheap as expected, then the result is just that the construction is… more expensive than expected. It would still be semantically <em>correct</em>, it’s just less efficient than ideal? That’s not usually the line to draw for ill-formed, no diagnostic required.</p>
<p>Furthermore, what actual operations do we need to be cheap? Consider this refinement:</p>
<blockquote>
<div class="sourceCode" id="cb8"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb8-1"><a href="#cb8-1"></a><span class="kw">struct</span> bad_view2 <span class="op">:</span> view_interface<span class="op"><</span>bad_view2<span class="op">></span> <span class="op">{</span></span>
<span id="cb8-2"><a href="#cb8-2"></a> std<span class="op">::</span>vector<span class="op"><</span><span class="dt">int</span><span class="op">></span> v;</span>
<span id="cb8-3"><a href="#cb8-3"></a> </span>
<span id="cb8-4"><a href="#cb8-4"></a> bad_view2<span class="op">(</span>std<span class="op">::</span>vector<span class="op"><</span><span class="dt">int</span><span class="op">></span> v<span class="op">)</span> <span class="op">:</span> v<span class="op">(</span>std<span class="op">::</span>move<span class="op">(</span>v<span class="op">))</span> <span class="op">{</span> <span class="op">}</span></span>
<span id="cb8-5"><a href="#cb8-5"></a> </span>
<span id="cb8-6"><a href="#cb8-6"></a> <span class="co">// movable, but not copyable</span></span>
<span id="cb8-7"><a href="#cb8-7"></a> bad_view2<span class="op">(</span>bad_view2 <span class="kw">const</span><span class="op">&)</span> <span class="op">=</span> <span class="kw">delete</span>;</span>
<span id="cb8-8"><a href="#cb8-8"></a> bad_view2<span class="op">(</span>bad_view2<span class="op">&&)</span> <span class="op">=</span> <span class="cf">default</span>;</span>
<span id="cb8-9"><a href="#cb8-9"></a> bad_view2<span class="op">&</span> <span class="kw">operator</span><span class="op">=(</span>bad_view2 <span class="kw">const</span><span class="op">&)</span> <span class="op">=</span> <span class="kw">delete</span>;</span>
<span id="cb8-10"><a href="#cb8-10"></a> bad_view2<span class="op">&</span> <span class="kw">operator</span><span class="op">+(</span>bad_view2<span class="op">&&)</span> <span class="op">=</span> <span class="cf">default</span>;</span>
<span id="cb8-11"><a href="#cb8-11"></a> </span>
<span id="cb8-12"><a href="#cb8-12"></a> std<span class="op">::</span>vector<span class="op"><</span><span class="dt">int</span><span class="op">>::</span>iterator begin<span class="op">()</span> <span class="op">{</span> <span class="cf">return</span> v<span class="op">.</span>begin<span class="op">()</span>; <span class="op">}</span></span>
<span id="cb8-13"><a href="#cb8-13"></a> std<span class="op">::</span>vector<span class="op"><</span><span class="dt">int</span><span class="op">>::</span>iterator end<span class="op">()</span> <span class="op">{</span> <span class="cf">return</span> v<span class="op">.</span>end<span class="op">()</span>; <span class="op">}</span></span>
<span id="cb8-14"><a href="#cb8-14"></a><span class="op">}</span>;</span>
<span id="cb8-15"><a href="#cb8-15"></a></span>
<span id="cb8-16"><a href="#cb8-16"></a>std<span class="op">::</span>vector<span class="op"><</span><span class="dt">int</span><span class="op">></span> get_ints<span class="op">()</span>;</span>
<span id="cb8-17"><a href="#cb8-17"></a></span>
<span id="cb8-18"><a href="#cb8-18"></a><span class="kw">auto</span> rng <span class="op">=</span> bad_view2<span class="op">(</span>get_ints<span class="op">())</span></span>
<span id="cb8-19"><a href="#cb8-19"></a> <span class="op">|</span> views<span class="op">::</span>filter<span class="op">([](</span><span class="dt">int</span> i<span class="op">){</span> <span class="cf">return</span> i <span class="op">></span> <span class="dv">0</span>; <span class="op">})</span></span>
<span id="cb8-20"><a href="#cb8-20"></a> <span class="op">|</span> views<span class="op">::</span>transform<span class="op">([](</span><span class="dt">int</span> i<span class="op">){</span> <span class="cf">return</span> i <span class="op">*</span> i; <span class="op">})</span>;</span></code></pre></div>
</blockquote>
<p>This whole construction involves moving a <code class="sourceCode cpp">vector<span class="op"><</span><span class="dt">int</span><span class="op">></span></code> twice (once into the <code class="sourceCode cpp">filter_view</code> and once into the <code class="sourceCode cpp">transform_view</code>, both moving a <code class="sourceCode cpp">vector<span class="op"><</span><span class="dt">int</span><span class="op">></span></code> is cheap) and destroying a <code class="sourceCode cpp">vector<span class="op"><</span><span class="dt">int</span><span class="op">></span></code> three times (twice when the source is empty, and once eventually when we’re destroying <code class="sourceCode cpp">rng</code> - it’s this last one that is not O(1)).</p>
<p>In contrast, the ordained method for writing this code is actually:</p>
<blockquote>
<div class="sourceCode" id="cb9"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb9-1"><a href="#cb9-1"></a><span class="kw">auto</span> ints <span class="op">=</span> get_ints<span class="op">()</span>; <span class="co">// must stash this into a variable first</span></span>
<span id="cb9-2"><a href="#cb9-2"></a><span class="kw">auto</span> rng <span class="op">=</span> ints</span>
<span id="cb9-3"><a href="#cb9-3"></a> <span class="op">|</span> views<span class="op">::</span>filter<span class="op">([](</span><span class="dt">int</span> i<span class="op">){</span> <span class="cf">return</span> i <span class="op">></span> <span class="dv">0</span>; <span class="op">})</span></span>
<span id="cb9-4"><a href="#cb9-4"></a> <span class="op">|</span> views<span class="op">::</span>transform<span class="op">([](</span><span class="dt">int</span> i<span class="op">){</span> <span class="cf">return</span> i <span class="op">*</span> i; <span class="op">})</span>;</span></code></pre></div>
</blockquote>
<p>Now, this no longer involves any moves of a <code class="sourceCode cpp">vector<span class="op"><</span><span class="dt">int</span><span class="op">></span></code>, since <code class="sourceCode cpp">rng</code> will instead be holding a <code class="sourceCode cpp">ref_view</code> into it, so this is in some sense cheaper. But this still, in the end, requires destroying that <code class="sourceCode cpp">vector<span class="op"><</span><span class="dt">int</span><span class="op">></span></code> - it’s just that this cost is paid by destroying <code class="sourceCode cpp">ints</code> rather than destroying <code class="sourceCode cpp">rng</code> in this formulation. That’s not meaningfully different. And moreover, there’s real cost to be paid by the latter formulation: now <code class="sourceCode cpp">rng</code> has an internal reference into <code class="sourceCode cpp">ints</code>, which both means that we have to be more careful because we can dangle (not an issue in the <code class="sourceCode cpp">bad_view2</code> formulation) and that we have an extra indirection through a pointer which could have performance impact.</p>
<p>Which is ironic, given that it’s the performance consideration which makes <code class="sourceCode cpp">bad_view2</code> bad.</p>
<p>Let’s consider relaxing the requirements as follows:</p>
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_2" id="pnum_2">2</a></span> <code class="sourceCode cpp">T</code> models <code class="sourceCode cpp">view</code> only if:</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_3" id="pnum_3">(2.1)</a></span> <code class="sourceCode cpp">T</code> has O(1) move construction; and</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_4" id="pnum_4">(2.2)</a></span> <code class="sourceCode cpp">T</code> has O(1) move assignment; and</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_5" id="pnum_5">(2.3)</a></span> <span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default">T</code></span> has O(1) destruction</del></span> <span class="addu">if <code class="sourceCode cpp">N</code> moves are made from an object of type <code class="sourceCode cpp">T</code> that contained <code class="sourceCode cpp">M</code> elements, then those <code class="sourceCode cpp">N</code> objects have <code class="sourceCode cpp">O<span class="op">(</span>N<span class="op">+</span>M<span class="op">)</span></code> destruction</span>; and</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_6" id="pnum_6">(2.4)</a></span> <code class="sourceCode cpp">copy_constructible<span class="op"><</span>T<span class="op">></span></code> is <code class="sourceCode cpp"><span class="kw">false</span></code>, or <code class="sourceCode cpp">T</code> has O(1) copy construction; and</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_7" id="pnum_7">(2.5)</a></span> <code class="sourceCode cpp">copyable<span class="op"><</span>T<span class="op">></span></code> is <code class="sourceCode cpp"><span class="kw">false</span></code>, or <code class="sourceCode cpp">T</code> has O(1) copy assignment.</li>
</ul>
</blockquote>
<p>Or, alternatively:</p>
<blockquote>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_8" id="pnum_8">(2.3)</a></span> <span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default">T</code></span> has</del></span> <span class="addu">an object of type <code class="sourceCode cpp">T</code> that has been moved from</span> has O(1) destruction; and</li>
</ul>
</blockquote>
<p>In this formulation, <code class="sourceCode cpp">bad_view</code> is still a bad view (because it is copyable and copying it is expensive - which is important because building up a range adaptor pipeline using lvalue views will try to copy them) but <code class="sourceCode cpp">bad_view2</code> is actually totally fine (and indeed, it is not more expensive than the alternate formulation).</p>
<p>In this formulation, <code class="sourceCode cpp">std<span class="op">::</span>generator<span class="op"><</span>T<span class="op">></span></code> is definitely a <code class="sourceCode cpp">view</code> that does not violate any of the semantic requirements.</p>
<p>This formulation has another extremely significant consequence. <span class="citation" data-cites="N4128">[<a href="#ref-N4128" role="doc-biblioref">N4128</a>]</span> stated:</p>
<div class="quote">
<p>[Views] are lightweight objects that refer to elements they do not own. As a result, they can guarantee O(1) copyability and assignability.</p>
</div>
<p>But this would no longer <em>necessarily</em> have to be the case. Consider the following:</p>
<blockquote>
<div class="sourceCode" id="cb10"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb10-1"><a href="#cb10-1"></a><span class="kw">template</span> <span class="op"><</span>range R<span class="op">></span> <span class="kw">requires</span> is_object_v<span class="op"><</span>R<span class="op">></span> <span class="op">&&</span> movable<span class="op"><</span>R<span class="op">></span></span>
<span id="cb10-2"><a href="#cb10-2"></a><span class="kw">class</span> owning_view <span class="op">:</span> <span class="kw">public</span> view_interface<span class="op"><</span>owning_view<span class="op"><</span>R<span class="op">>></span> <span class="op">{</span></span>
<span id="cb10-3"><a href="#cb10-3"></a> R r_; <span class="co">// exposition only</span></span>
<span id="cb10-4"><a href="#cb10-4"></a> </span>
<span id="cb10-5"><a href="#cb10-5"></a><span class="kw">public</span><span class="op">:</span></span>
<span id="cb10-6"><a href="#cb10-6"></a> owning_view<span class="op">()</span> <span class="op">=</span> <span class="cf">default</span>;</span>
<span id="cb10-7"><a href="#cb10-7"></a> <span class="kw">constexpr</span> owning_view<span class="op">(</span>R<span class="op">&&</span> t<span class="op">)</span>;</span>
<span id="cb10-8"><a href="#cb10-8"></a> </span>
<span id="cb10-9"><a href="#cb10-9"></a> owning_view<span class="op">(</span><span class="kw">const</span> owning_view<span class="op">&)</span> <span class="op">=</span> <span class="kw">delete</span>;</span>
<span id="cb10-10"><a href="#cb10-10"></a> owning_view<span class="op">(</span>owning_view<span class="op">&&)</span> <span class="op">=</span> <span class="cf">default</span>;</span>
<span id="cb10-11"><a href="#cb10-11"></a> owning_view<span class="op">&</span> <span class="kw">operator</span><span class="op">=(</span><span class="kw">const</span> owning_view<span class="op">&)</span> <span class="op">=</span> <span class="kw">delete</span>;</span>
<span id="cb10-12"><a href="#cb10-12"></a> owning_view<span class="op">&</span> <span class="kw">operator</span><span class="op">=(</span>owning_view<span class="op">&&)</span> <span class="op">=</span> <span class="cf">default</span>;</span>
<span id="cb10-13"><a href="#cb10-13"></a></span>
<span id="cb10-14"><a href="#cb10-14"></a> <span class="kw">constexpr</span> R<span class="op">&</span> base<span class="op">()</span> <span class="op">&</span> <span class="op">{</span> <span class="cf">return</span> r_; <span class="op">}</span></span>
<span id="cb10-15"><a href="#cb10-15"></a> <span class="kw">constexpr</span> <span class="kw">const</span> R<span class="op">&</span> base<span class="op">()</span> <span class="kw">const</span><span class="op">&</span> <span class="op">{</span> <span class="cf">return</span> r_; <span class="op">}</span></span>
<span id="cb10-16"><a href="#cb10-16"></a> <span class="kw">constexpr</span> R<span class="op">&&</span> base<span class="op">()</span> <span class="op">&&</span> <span class="op">{</span> <span class="cf">return</span> std<span class="op">::</span>move<span class="op">(</span>r_<span class="op">)</span>; <span class="op">}</span></span>
<span id="cb10-17"><a href="#cb10-17"></a> <span class="kw">constexpr</span> <span class="kw">const</span> R<span class="op">&&</span> base<span class="op">()</span> <span class="kw">const</span><span class="op">&&</span> <span class="op">{</span> <span class="cf">return</span> std<span class="op">::</span>move<span class="op">(</span>r_<span class="op">)</span>; <span class="op">}</span></span>
<span id="cb10-18"><a href="#cb10-18"></a></span>
<span id="cb10-19"><a href="#cb10-19"></a> <span class="kw">constexpr</span> iterator_t<span class="op"><</span>R<span class="op">></span> begin<span class="op">()</span> <span class="op">{</span> <span class="cf">return</span> ranges<span class="op">::</span>begin<span class="op">(</span>r_<span class="op">)</span>; <span class="op">}</span></span>
<span id="cb10-20"><a href="#cb10-20"></a> <span class="kw">constexpr</span> iterator_t<span class="op"><</span><span class="kw">const</span> R<span class="op">></span> begin<span class="op">()</span> <span class="kw">const</span> <span class="kw">requires</span> range<span class="op"><</span><span class="kw">const</span> R<span class="op">>{</span> <span class="cf">return</span> ranges<span class="op">::</span>begin<span class="op">(</span>r_<span class="op">)</span>; <span class="op">}</span></span>
<span id="cb10-21"><a href="#cb10-21"></a> </span>
<span id="cb10-22"><a href="#cb10-22"></a> <span class="kw">constexpr</span> sentinel_t<span class="op"><</span>R<span class="op">></span> end<span class="op">()</span> <span class="op">{</span> <span class="cf">return</span> ranges<span class="op">::</span>end<span class="op">(</span>r_<span class="op">)</span>; <span class="op">}</span></span>
<span id="cb10-23"><a href="#cb10-23"></a> <span class="kw">constexpr</span> sentinel_t<span class="op"><</span><span class="kw">const</span> R<span class="op">></span> end<span class="op">()</span> <span class="kw">const</span> <span class="kw">requires</span> range<span class="op"><</span><span class="kw">const</span> R<span class="op">></span> <span class="op">{</span> <span class="cf">return</span> ranges<span class="op">::</span>end<span class="op">(</span>r_<span class="op">)</span>; <span class="op">}</span></span>
<span id="cb10-24"><a href="#cb10-24"></a></span>
<span id="cb10-25"><a href="#cb10-25"></a></span>
<span id="cb10-26"><a href="#cb10-26"></a> <span class="co">// + overloads for empty, size, data</span></span>
<span id="cb10-27"><a href="#cb10-27"></a><span class="op">}</span>;</span>
<span id="cb10-28"><a href="#cb10-28"></a> </span>
<span id="cb10-29"><a href="#cb10-29"></a><span class="kw">template</span> <span class="op"><</span><span class="kw">class</span> R<span class="op">></span></span>
<span id="cb10-30"><a href="#cb10-30"></a>owning_view<span class="op">(</span>R<span class="op">&&)</span> <span class="op">-></span> owning_view<span class="op"><</span>R<span class="op">></span>;</span></code></pre></div>
</blockquote>
<p>An <code class="sourceCode cpp">owning_view<span class="op"><</span>vector<span class="op"><</span><span class="dt">int</span><span class="op">>></span></code> would completely satisfy the semantics of <code class="sourceCode cpp">view</code>: it is not copyable, it is O(1) movable, and moved-from object would be O(1) destructible. All without sacrificing any of the benefit that views provide: cheap construction of range adaptor pipelines.</p>
<p>Adopting these semantics, along with <code class="sourceCode cpp">owning_view</code>, would further allow us to respecify <code class="sourceCode cpp">views<span class="op">::</span>all</code> (<span>24.7.5 <a href="https://wg21.link/range.all">[range.all]</a></span>) as:</p>
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_9" id="pnum_9">2</a></span> The name <code class="sourceCode cpp">views<span class="op">::</span>all</code> denotes a range adaptor object ([range.adaptor.object]). Given a subexpression <code class="sourceCode cpp">E</code>, the expression <code class="sourceCode cpp">views<span class="op">::</span>all<span class="op">(</span>E<span class="op">)</span></code> is expression-equivalent to:</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_10" id="pnum_10">(2.1)</a></span> <code class="sourceCode cpp"><em>decay-copy</em><span class="op">(</span>E<span class="op">)</span></code> if the decayed type of <code class="sourceCode cpp">E</code> models <code class="sourceCode cpp">view</code>.</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_11" id="pnum_11">(2.2)</a></span> Otherwise, <code class="sourceCode cpp">ref_view<span class="op">{</span>E<span class="op">}</span></code> if that expression is well-formed.</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_12" id="pnum_12">(2.3)</a></span> Otherwise, <span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default">subrange{E}</code></span></del></span> <span class="addu"><code class="sourceCode cpp">owning_view<span class="op">{</span>E<span class="op">}</span></code></span>.</li>
</ul>
</blockquote>
<p>The first sub-bullet effectively rejects using lvalue non-copyable views, as desired. Then the second bullet captures lvalue non-view ranges by reference and the new third bullet<a href="#fn3" class="footnote-ref" id="fnref3" role="doc-noteref"><sup>3</sup></a> would capture rvalue non-view ranges by ownership. This is safer and more ergonomic too.</p>
<p>Making the above change implies we also need to respecify <code class="sourceCode cpp">viewable_range</code> (in <span>24.4.5 <a href="https://wg21.link/range.refinements">[range.refinements]</a></span>/5), since this concept and <code class="sourceCode cpp">views<span class="op">::</span>all</code> need to stay in sync:</p>
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_13" id="pnum_13">5</a></span> The <code class="sourceCode cpp">viewable_range</code> concept specifies the requirements of a <code class="sourceCode cpp">range</code> type that can be converted to a <code class="sourceCode cpp">view</code> safely.</p>
<div class="sourceCode" id="cb11"><pre class="sourceCode default"><code class="sourceCode default"><span id="cb11-1"><a href="#cb11-1"></a>template<class T></span>
<span id="cb11-2"><a href="#cb11-2"></a> concept viewable_range =</span>
<span id="cb11-3"><a href="#cb11-3"></a> range<T> &&</span>
<span id="cb11-4"><a href="#cb11-4"></a> ((view<remove_cvref_t<T>> && constructible_from<remove_cvref_t<T>, T>) ||</span>
<span id="cb11-5"><a href="#cb11-5"></a> (!view<remove_cvref_t<T>> && <span class="rm" style="color: #bf0303"><del>borrowed_range<T></del></span> <span class="addu">(is_lvalue_reference_v<T> || movable<remove_reference_t<T>>)</span>));</span></code></pre></div>
</blockquote>
<h1 data-number="5" style="border-bottom:1px solid #cccccc" id="what-is-a-view"><span class="header-section-number">5</span> What is a <code class="sourceCode cpp">view</code>?<a href="#what-is-a-view" class="self-link"></a></h1>
<p>Once upon a time, a <code class="sourceCode cpp">view</code> was a cheaply copyable, non-owning range. We’ve already somewhat lost the “cheaply copyable” requirement since views don’t have to be copyable, and now this paper is suggesting that we also lose the non-owning part.</p>
<p>So how do you answer the question now?</p>
<p>There may not be a clean answer, which is admittedly unsatisfying, but it mainly boils down to:</p>
<blockquote>
<div class="sourceCode" id="cb12"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb12-1"><a href="#cb12-1"></a><span class="kw">auto</span> rng <span class="op">=</span> v <span class="op">|</span> views<span class="op">::</span>reverse;</span></code></pre></div>
</blockquote>
<p>If <code class="sourceCode cpp">v</code> is an lvalue, do you want <code class="sourceCode cpp">rng</code> to <em>copy</em> <code class="sourceCode cpp">v</code> or to <em>refer</em> to <code class="sourceCode cpp">v</code>? If you want it to copy <code class="sourceCode cpp">v</code>, because copying <code class="sourceCode cpp">v</code> is cheap and you want to avoid paying for indirection and potentional dangling, then <code class="sourceCode cpp">v</code> is a <code class="sourceCode cpp">view</code>. If you want to refer to <code class="sourceCode cpp">v</code>, because copying <code class="sourceCode cpp">v</code> is expensive (possibly more expensive than the algorithm you’re doing), then <code class="sourceCode cpp">v</code> is not a view. <code class="sourceCode cpp">string_view</code> is a <code class="sourceCode cpp">view</code>, <code class="sourceCode cpp">vector<span class="op"><</span>string<span class="op">></span></code> is not.</p>
<h1 data-number="6" style="border-bottom:1px solid #cccccc" id="implementation-experience"><span class="header-section-number">6</span> Implementation Experience<a href="#implementation-experience" class="self-link"></a></h1>
<p>This proposal has been implemented and passes the libstdc++ testsuite (with suitable modifications).</p>
<h1 data-number="7" style="border-bottom:1px solid #cccccc" id="proposed-wording"><span class="header-section-number">7</span> Proposed Wording<a href="#proposed-wording" class="self-link"></a></h1>
<p>This also resolves <span class="citation" data-cites="LWG3452">[<a href="#ref-LWG3452" role="doc-biblioref">LWG3452</a>]</span>.</p>
<p>Update <span>17.3.2 <a href="https://wg21.link/version.syn">[version.syn]</a></span></p>
<blockquote>
<div>
<div class="sourceCode" id="cb13"><pre class="sourceCode diff"><code class="sourceCode diff"><span id="cb13-1"><a href="#cb13-1"></a><span class="st">- #define __cpp_lib_ranges <span class="diffdel">202106L</span></span></span>
<span id="cb13-2"><a href="#cb13-2"></a><span class="va">+ #define __cpp_lib_ranges <span class="diffins">2021XXL</span></span></span>
<span id="cb13-3"><a href="#cb13-3"></a> // also in <algorithm>, <functional>, <iterator>, <memory>, <ranges></span></code></pre></div>
</div>
</blockquote>
<p>Add <code class="sourceCode cpp">owning_view</code> to <span>24.2 <a href="https://wg21.link/ranges.syn">[ranges.syn]</a></span>:</p>
<blockquote>
<div>
<div class="sourceCode" id="cb14"><pre class="sourceCode diff"><code class="sourceCode diff"><span id="cb14-1"><a href="#cb14-1"></a>#include <compare> // see [compare.syn]</span>
<span id="cb14-2"><a href="#cb14-2"></a>#include <initializer_list> // see [initializer.list.syn]</span>
<span id="cb14-3"><a href="#cb14-3"></a>#include <iterator> // see [iterator.synopsis]</span>
<span id="cb14-4"><a href="#cb14-4"></a></span>
<span id="cb14-5"><a href="#cb14-5"></a>namespace std::ranges {</span>
<span id="cb14-6"><a href="#cb14-6"></a> // ...</span>
<span id="cb14-7"><a href="#cb14-7"></a> </span>
<span id="cb14-8"><a href="#cb14-8"></a> // [range.all], all view</span>
<span id="cb14-9"><a href="#cb14-9"></a> namespace views {</span>
<span id="cb14-10"><a href="#cb14-10"></a> inline constexpr <em>unspecified</em> all = <em>unspecified</em>;</span>
<span id="cb14-11"><a href="#cb14-11"></a></span>
<span id="cb14-12"><a href="#cb14-12"></a> template<viewable_range R></span>
<span id="cb14-13"><a href="#cb14-13"></a> using all_t = decltype(all(declval<R>()));</span>
<span id="cb14-14"><a href="#cb14-14"></a> }</span>
<span id="cb14-15"><a href="#cb14-15"></a></span>
<span id="cb14-16"><a href="#cb14-16"></a> template<range R></span>
<span id="cb14-17"><a href="#cb14-17"></a> requires is_object_v<R></span>
<span id="cb14-18"><a href="#cb14-18"></a> class ref_view;</span>
<span id="cb14-19"><a href="#cb14-19"></a></span>
<span id="cb14-20"><a href="#cb14-20"></a> template<class T></span>
<span id="cb14-21"><a href="#cb14-21"></a> inline constexpr bool enable_borrowed_range<ref_view<T>> = true;</span>
<span id="cb14-22"><a href="#cb14-22"></a></span>
<span id="cb14-23"><a href="#cb14-23"></a><span class="va">+ template<range R></span></span>
<span id="cb14-24"><a href="#cb14-24"></a><span class="va">+ requires <em>see below</em></span></span>
<span id="cb14-25"><a href="#cb14-25"></a><span class="va">+ class owning_view;</span></span>
<span id="cb14-26"><a href="#cb14-26"></a><span class="va">+ </span></span>
<span id="cb14-27"><a href="#cb14-27"></a><span class="va">+ template<class T></span></span>
<span id="cb14-28"><a href="#cb14-28"></a><span class="va">+ inline constexpr bool enable_borrowed_range<owning_view<T>> = enable_borrowed_range<T>; </span></span>
<span id="cb14-29"><a href="#cb14-29"></a></span>
<span id="cb14-30"><a href="#cb14-30"></a> // ... </span>
<span id="cb14-31"><a href="#cb14-31"></a>}</span></code></pre></div>
</div>
</blockquote>
<p>Relax the requirements on <code class="sourceCode cpp">view</code> in <span>24.4.4 <a href="https://wg21.link/range.view">[range.view]</a></span>:</p>
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_14" id="pnum_14">1</a></span> The <code class="sourceCode cpp">view</code> concept specifies the requirements of a <code class="sourceCode cpp">range</code> type that has <span class="rm" style="color: #bf0303"><del>constant time move construction, move assignment, and destruction; that is, the cost of these operations is independent of the number of elements in the <span><code class="sourceCode default">view</code></span></del></span> <span class="addu">the semantic properties below, which make it suitable for use in constructing range adaptor pipelines ([range.adaptors])</span>.</p>
<div class="sourceCode" id="cb15"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb15-1"><a href="#cb15-1"></a><span class="kw">template</span><span class="op"><</span><span class="kw">class</span> T<span class="op">></span></span>
<span id="cb15-2"><a href="#cb15-2"></a> <span class="kw">concept</span> view <span class="op">=</span></span>
<span id="cb15-3"><a href="#cb15-3"></a> range<span class="op"><</span>T<span class="op">></span> <span class="op">&&</span> movable<span class="op"><</span>T<span class="op">></span> <span class="op">&&</span> enable_view<span class="op"><</span>T<span class="op">></span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_15" id="pnum_15">2</a></span> <code class="sourceCode cpp">T</code> models <code class="sourceCode cpp">view</code> only if:</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_16" id="pnum_16">(2.1)</a></span> <code class="sourceCode cpp">T</code> has <code class="sourceCode cpp">O<span class="op">(</span><span class="dv">1</span><span class="op">)</span></code> move construction; and</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_17" id="pnum_17">(2.2)</a></span> <span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default">T</code></span> has <span><code class="sourceCode default">O(1)</code></span> move assignment</del></span> <span class="addu">move assignment of an object of type <code class="sourceCode cpp">T</code> is no more complex than destruction followed by move construction</span>; and</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_18" id="pnum_18">(2.3)</a></span> <span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default">T</code></span> has <span><code class="sourceCode default">O(1)</code></span> destruction</del></span> <span class="addu">if <code class="sourceCode cpp">N</code> copies and/or moves are made from an object of type <code class="sourceCode cpp">T</code> that contained <code class="sourceCode cpp">M</code> elements, then those <code class="sourceCode cpp">N</code> objects have <code class="sourceCode cpp">O<span class="op">(</span>N<span class="op">+</span>M<span class="op">)</span></code> destruction [<em>Note</em>: this implies that a moved-from object of type <code class="sourceCode cpp">T</code> has <code class="sourceCode cpp">O<span class="op">(</span><span class="dv">1</span><span class="op">)</span></code> destruction -<em>end note</em>]</span>; and</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_19" id="pnum_19">(2.4)</a></span> <code class="sourceCode cpp">copy_constructible<span class="op"><</span>T<span class="op">></span></code> is <code class="sourceCode cpp"><span class="kw">false</span></code>, or <code class="sourceCode cpp">T</code> has <code class="sourceCode cpp">O<span class="op">(</span><span class="dv">1</span><span class="op">)</span></code> copy construction; and</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_20" id="pnum_20">(2.5)</a></span> <code class="sourceCode cpp">copyable<span class="op"><</span>T<span class="op">></span></code> is <code class="sourceCode cpp"><span class="kw">false</span></code>, or <span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default">T</code></span> has <span><code class="sourceCode default">O(1)</code></span> copy assignment</del></span> <span class="addu">copy assignment of an object of type <code class="sourceCode cpp">T</code> is no more complex than destruction followed by copy construction</span>.</li>
</ul>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_21" id="pnum_21">3</a></span> [<em>Example 1</em>: Examples of <code class="sourceCode cpp">view</code>s are:</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_22" id="pnum_22">(3.1)</a></span> A range type that wraps a pair of iterators.</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_23" id="pnum_23">(3.2)</a></span> A range type that holds its elements by <code class="sourceCode cpp">shared_ptr</code> and shares ownership with all its copies.</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_24" id="pnum_24">(3.3)</a></span> A range type that generates its elements on demand.</li>
</ul>
<p><span class="rm" style="color: #bf0303"><del>Most containers are not views</del></span> <span class="addu">A container such as <code class="sourceCode cpp">vector<span class="op"><</span>string<span class="op">></span></code> does not meet the semantic requirements of <code class="sourceCode cpp">view</code></span> since <span class="rm" style="color: #bf0303"><del>destruction of</del></span> <span class="addu">copying</span> the container <span class="rm" style="color: #bf0303"><del>destroys</del></span> <span class="addu">copies all of</span> the elements, which cannot be done in constant time. — <em>end example</em>]</p>
</blockquote>
<p>Change the definition of <code class="sourceCode cpp">viewable_range</code> to line up with <code class="sourceCode cpp">views<span class="op">::</span>all</code> (see later) in <span>24.4.5 <a href="https://wg21.link/range.refinements">[range.refinements]</a></span>, inserting the new exposition-only variable template <code class="sourceCode cpp"><em>is-initializer-list</em><span class="op"><</span>T<span class="op">></span></code> <span class="ednote" style="color: #0000ff">[ Editor's note: <code class="sourceCode default">remove_reference_t</code> rather than <code class="sourceCode default">remove_cvref_t</code> because we need to reject <code class="sourceCode default">const vector<int>&&</code> from being a <code class="sourceCode default">viewable_range</code> ]</span>:</p>
<blockquote>
<div class="addu">
<div class="sourceCode" id="cb16"><pre class="sourceCode default"><code class="sourceCode default"><span id="cb16-1"><a href="#cb16-1"></a>template <class R></span>
<span id="cb16-2"><a href="#cb16-2"></a> inline constexpr bool <em>is-initializer-list</em> = <em>see below</em>; // exposition only</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_25" id="pnum_25">*</a></span> For a type <code class="sourceCode cpp">R</code>, <code class="sourceCode cpp"><em>is-initializer-list</em><span class="op"><</span>R<span class="op">></span></code> is <code class="sourceCode cpp"><span class="kw">true</span></code> if and only if <code class="sourceCode cpp">remove_cvref_t<span class="op"><</span>R<span class="op">></span></code> is a specialization of <code class="sourceCode cpp">initializer_list</code>.</p>
</div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_26" id="pnum_26">5</a></span> The <code class="sourceCode cpp">viewable_range</code> concept specifies the requirements of a <code class="sourceCode cpp">range</code> type that can be converted to a <code class="sourceCode cpp">view</code> safely.</p>
<div class="sourceCode" id="cb17"><pre class="sourceCode default"><code class="sourceCode default"><span id="cb17-1"><a href="#cb17-1"></a>template<class T></span>
<span id="cb17-2"><a href="#cb17-2"></a>concept viewable_range =</span>
<span id="cb17-3"><a href="#cb17-3"></a> range<T> &&</span>
<span id="cb17-4"><a href="#cb17-4"></a> ((view<remove_cvref_t<T>> && constructible_from<remove_cvref_t<T>, T>) ||</span>
<span id="cb17-5"><a href="#cb17-5"></a> (!view<remove_cvref_t<T>> && <span class="rm" style="color: #bf0303"><del>borrowed_range<T></del></span></span>
<span id="cb17-6"><a href="#cb17-6"></a> <span class="addu">(is_lvalue_reference_v<T> || (movable<remove_reference_t<T>> && !<em>is-initializer-list</em><T>))</span>));</span></code></pre></div>
</blockquote>
<p>Change the last bullet in the definition of <code class="sourceCode cpp">views<span class="op">::</span>all</code> in <span>24.7.5.1 <a href="https://wg21.link/range.all.general">[range.all.general]</a></span>:</p>
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_27" id="pnum_27">2</a></span> The name <code class="sourceCode cpp">views<span class="op">::</span>all</code> denotes a range adaptor object ([range.adaptor.object]). Given a subexpression <code class="sourceCode cpp">E</code>, the expression <code class="sourceCode cpp">views<span class="op">::</span>all<span class="op">(</span>E<span class="op">)</span></code> is expression-equivalent to:</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_28" id="pnum_28">(2.1)</a></span> <code class="sourceCode cpp"><em>decay-copy</em><span class="op">(</span>E<span class="op">)</span></code> if the decayed type of <code class="sourceCode cpp">E</code> models <code class="sourceCode cpp">view</code>.</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_29" id="pnum_29">(2.2)</a></span> Otherwise, <code class="sourceCode cpp">ref_view<span class="op">{</span>E<span class="op">}</span></code> if that expression is well-formed.</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_30" id="pnum_30">(2.3)</a></span> Otherwise, <span class="rm" style="color: #bf0303"><del><span><code class="sourceCode default">subrange{E}</code></span></del></span> <span class="addu"><code class="sourceCode cpp">owning_view<span class="op">{</span>E<span class="op">}</span></code></span>.</li>
</ul>
</blockquote>
<p>Add a new subclause under [range.all] directly after <span>24.7.5.2 <a href="https://wg21.link/range.ref.view">[range.ref.view]</a></span> named “Class template <code class="sourceCode cpp">owning_view</code>” with stable name [range.owning.view]:</p>
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_31" id="pnum_31">1</a></span> <code class="sourceCode cpp">owning_view</code> is a move-only <code class="sourceCode cpp">view</code> of the elements of some other <code class="sourceCode cpp">range</code>.</p>
<div class="sourceCode" id="cb18"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb18-1"><a href="#cb18-1"></a><span class="kw">namespace</span> std<span class="op">::</span>ranges <span class="op">{</span></span>
<span id="cb18-2"><a href="#cb18-2"></a> <span class="kw">template</span><span class="op"><</span>range R<span class="op">></span></span>
<span id="cb18-3"><a href="#cb18-3"></a> <span class="kw">requires</span> movable<span class="op"><</span>R<span class="op">></span> <span class="op">&&</span> <span class="op">(!</span><em>is-initializer-list</em><span class="op"><</span>R<span class="op">>)</span> <span class="co">// see [range.refinements]</span></span>
<span id="cb18-4"><a href="#cb18-4"></a> <span class="kw">class</span> owning_view <span class="op">:</span> <span class="kw">public</span> view_interface<span class="op"><</span>owning_view<span class="op"><</span>R<span class="op">>></span> <span class="op">{</span></span>
<span id="cb18-5"><a href="#cb18-5"></a> <span class="kw">private</span><span class="op">:</span></span>
<span id="cb18-6"><a href="#cb18-6"></a> R <em>r_</em> <span class="op">=</span> R<span class="op">()</span>; <span class="co">// exposition only</span></span>
<span id="cb18-7"><a href="#cb18-7"></a> <span class="kw">public</span><span class="op">:</span></span>
<span id="cb18-8"><a href="#cb18-8"></a> owning_view<span class="op">()</span> <span class="kw">requires</span> default_initializable<span class="op"><</span>R<span class="op">></span> <span class="op">=</span> <span class="cf">default</span>;</span>
<span id="cb18-9"><a href="#cb18-9"></a> <span class="kw">constexpr</span> owning_view<span class="op">(</span>R<span class="op">&&</span> t<span class="op">)</span>;</span>
<span id="cb18-10"><a href="#cb18-10"></a></span>
<span id="cb18-11"><a href="#cb18-11"></a> owning_view<span class="op">(</span>owning_view<span class="op">&&)</span> <span class="op">=</span> <span class="cf">default</span>;</span>
<span id="cb18-12"><a href="#cb18-12"></a> owning_view<span class="op">&</span> <span class="kw">operator</span><span class="op">=(</span>owning_view<span class="op">&&)</span> <span class="op">=</span> <span class="cf">default</span>;</span>
<span id="cb18-13"><a href="#cb18-13"></a></span>
<span id="cb18-14"><a href="#cb18-14"></a> <span class="kw">constexpr</span> R<span class="op">&</span> base<span class="op">()</span> <span class="op">&</span> <span class="kw">noexcept</span> <span class="op">{</span> <span class="cf">return</span> <em>r_</em>; <span class="op">}</span></span>
<span id="cb18-15"><a href="#cb18-15"></a> <span class="kw">constexpr</span> <span class="kw">const</span> R<span class="op">&</span> base<span class="op">()</span> <span class="kw">const</span><span class="op">&</span> <span class="kw">noexcept</span> <span class="op">{</span> <span class="cf">return</span> <em>r_</em>; <span class="op">}</span></span>
<span id="cb18-16"><a href="#cb18-16"></a> <span class="kw">constexpr</span> R<span class="op">&&</span> base<span class="op">()</span> <span class="op">&&</span> <span class="kw">noexcept</span> <span class="op">{</span> <span class="cf">return</span> std<span class="op">::</span>move<span class="op">(</span><em>r_</em><span class="op">)</span>; <span class="op">}</span></span>
<span id="cb18-17"><a href="#cb18-17"></a> <span class="kw">constexpr</span> <span class="kw">const</span> R<span class="op">&&</span> base<span class="op">()</span> <span class="kw">const</span><span class="op">&&</span> <span class="kw">noexcept</span> <span class="op">{</span> <span class="cf">return</span> std<span class="op">::</span>move<span class="op">(</span><em>r_</em><span class="op">)</span>; <span class="op">}</span></span>
<span id="cb18-18"><a href="#cb18-18"></a></span>
<span id="cb18-19"><a href="#cb18-19"></a> <span class="kw">constexpr</span> iterator_t<span class="op"><</span>R<span class="op">></span> begin<span class="op">()</span> <span class="op">{</span> <span class="cf">return</span> ranges<span class="op">::</span>begin<span class="op">(</span><em>r_</em><span class="op">)</span>; <span class="op">}</span></span>
<span id="cb18-20"><a href="#cb18-20"></a> <span class="kw">constexpr</span> sentinel_t<span class="op"><</span>R<span class="op">></span> end<span class="op">()</span> <span class="op">{</span> <span class="cf">return</span> ranges<span class="op">::</span>end<span class="op">(</span><em>r_</em><span class="op">)</span>; <span class="op">}</span></span>
<span id="cb18-21"><a href="#cb18-21"></a> </span>
<span id="cb18-22"><a href="#cb18-22"></a> <span class="kw">constexpr</span> <span class="kw">auto</span> begin<span class="op">()</span> <span class="kw">const</span> <span class="kw">requires</span> range<span class="op"><</span><span class="kw">const</span> R<span class="op">></span></span>
<span id="cb18-23"><a href="#cb18-23"></a> <span class="op">{</span> <span class="cf">return</span> ranges<span class="op">::</span>begin<span class="op">(</span><em>r_</em><span class="op">)</span>; <span class="op">}</span></span>
<span id="cb18-24"><a href="#cb18-24"></a> <span class="kw">constexpr</span> <span class="kw">auto</span> end<span class="op">()</span> <span class="kw">const</span> <span class="kw">requires</span> range<span class="op"><</span><span class="kw">const</span> R<span class="op">></span></span>
<span id="cb18-25"><a href="#cb18-25"></a> <span class="op">{</span> <span class="cf">return</span> ranges<span class="op">::</span>end<span class="op">(</span><em>r_</em><span class="op">)</span>; <span class="op">}</span></span>
<span id="cb18-26"><a href="#cb18-26"></a></span>
<span id="cb18-27"><a href="#cb18-27"></a> <span class="kw">constexpr</span> <span class="dt">bool</span> empty<span class="op">()</span></span>
<span id="cb18-28"><a href="#cb18-28"></a> <span class="kw">requires</span> <span class="kw">requires</span> <span class="op">{</span> ranges<span class="op">::</span>empty<span class="op">(</span><em>r_</em><span class="op">)</span>; <span class="op">}</span></span>
<span id="cb18-29"><a href="#cb18-29"></a> <span class="op">{</span> <span class="cf">return</span> ranges<span class="op">::</span>empty<span class="op">(</span><em>r_</em><span class="op">)</span>; <span class="op">}</span> </span>
<span id="cb18-30"><a href="#cb18-30"></a> <span class="kw">constexpr</span> <span class="dt">bool</span> empty<span class="op">()</span> <span class="kw">const</span></span>
<span id="cb18-31"><a href="#cb18-31"></a> <span class="kw">requires</span> <span class="kw">requires</span> <span class="op">{</span> ranges<span class="op">::</span>empty<span class="op">(</span><em>r_</em><span class="op">)</span>; <span class="op">}</span></span>
<span id="cb18-32"><a href="#cb18-32"></a> <span class="op">{</span> <span class="cf">return</span> ranges<span class="op">::</span>empty<span class="op">(</span><em>r_</em><span class="op">)</span>; <span class="op">}</span></span>
<span id="cb18-33"><a href="#cb18-33"></a></span>
<span id="cb18-34"><a href="#cb18-34"></a> <span class="kw">constexpr</span> <span class="kw">auto</span> size<span class="op">()</span> <span class="kw">requires</span> sized_range<span class="op"><</span>R<span class="op">></span></span>
<span id="cb18-35"><a href="#cb18-35"></a> <span class="op">{</span> <span class="cf">return</span> ranges<span class="op">::</span>size<span class="op">(</span><em>r_</em><span class="op">)</span>; <span class="op">}</span></span>
<span id="cb18-36"><a href="#cb18-36"></a> <span class="kw">constexpr</span> <span class="kw">auto</span> size<span class="op">()</span> <span class="kw">const</span> <span class="kw">requires</span> sized_range<span class="op"><</span><span class="kw">const</span> R<span class="op">></span></span>
<span id="cb18-37"><a href="#cb18-37"></a> <span class="op">{</span> <span class="cf">return</span> ranges<span class="op">::</span>size<span class="op">(</span><em>r_</em><span class="op">)</span>; <span class="op">}</span></span>
<span id="cb18-38"><a href="#cb18-38"></a></span>
<span id="cb18-39"><a href="#cb18-39"></a> <span class="kw">constexpr</span> <span class="kw">auto</span> data<span class="op">()</span> <span class="kw">requires</span> contiguous_range<span class="op"><</span>R<span class="op">></span></span>
<span id="cb18-40"><a href="#cb18-40"></a> <span class="op">{</span> <span class="cf">return</span> ranges<span class="op">::</span>data<span class="op">(</span><em>r_</em><span class="op">)</span>; <span class="op">}</span></span>
<span id="cb18-41"><a href="#cb18-41"></a> <span class="kw">constexpr</span> <span class="kw">auto</span> data<span class="op">()</span> <span class="kw">const</span> <span class="kw">requires</span> contiguous_range<span class="op"><</span><span class="kw">const</span> R<span class="op">></span></span>
<span id="cb18-42"><a href="#cb18-42"></a> <span class="op">{</span> <span class="cf">return</span> ranges<span class="op">::</span>data<span class="op">(</span><em>r_</em><span class="op">)</span>; <span class="op">}</span></span>
<span id="cb18-43"><a href="#cb18-43"></a> <span class="op">}</span>;</span>
<span id="cb18-44"><a href="#cb18-44"></a><span class="op">}</span></span></code></pre></div>
<div class="sourceCode" id="cb19"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb19-1"><a href="#cb19-1"></a><span class="kw">constexpr</span> owning_view<span class="op">(</span>R<span class="op">&&</span> t<span class="op">)</span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_32" id="pnum_32">2</a></span> <em>Effects</em>: Initializes <code class="sourceCode cpp"><em>r_</em></code> with <code class="sourceCode cpp">std<span class="op">::</span>move<span class="op">(</span>t<span class="op">)</span></code>.</p>
</blockquote>
<h1 data-number="8" style="border-bottom:1px solid #cccccc" id="bibliography"><span class="header-section-number">8</span> References<a href="#bibliography" class="self-link"></a></h1>
<div id="refs" class="references hanging-indent" role="doc-bibliography">
<div id="ref-LWG3452">
<p>[LWG3452] Mathias Stearn. Are views really supposed to have strict 𝒪(1) destruction? <br />
<a href="https://wg21.link/lwg3452">https://wg21.link/lwg3452</a></p>
</div>
<div id="ref-N4128">
<p>[N4128] E. Niebler, S. Parent, A. Sutton. 2014-10-10. Ranges for the Standard Library, Revision 1. <br />
<a href="https://wg21.link/n4128">https://wg21.link/n4128</a></p>
</div>
<div id="ref-P1456R1">
<p>[P1456R1] Casey Carter. 2019-11-12. Move-only views. <br />
<a href="https://wg21.link/p1456r1">https://wg21.link/p1456r1</a></p>
</div>
<div id="ref-P2168R3">
<p>[P2168R3] Corentin Jabot, Lewis Baker. 2021-04-19. generator: A Synchronous Coroutine Generator Compatible With Ranges. <br />
<a href="https://wg21.link/p2168r3">https://wg21.link/p2168r3</a></p>
</div>
<div id="ref-P2325R3">
<p>[P2325R3] Barry Revzin. 2021-05-14. Views should not be required to be default constructible. <br />
<a href="https://wg21.link/p2325r3">https://wg21.link/p2325r3</a></p>
</div>
<div id="ref-P2415R0">
<p>[P2415R0] Barry Revzin, Tim Song. 2021-07-15. What is a view? <br />
<a href="https://wg21.link/p2415r0">https://wg21.link/p2415r0</a></p>
</div>
</div>
<section class="footnotes" role="doc-endnotes">
<hr />
<ol>
<li id="fn1" role="doc-endnote"><p>This is why they’re called <em>range</em> adaptors rather than <em>view</em> adaptors, perhaps that should change as well?<a href="#fnref1" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn2" role="doc-endnote"><p>except <code class="sourceCode cpp">views<span class="op">::</span>single</code><a href="#fnref2" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
<li id="fn3" role="doc-endnote"><p>the existing third bullet could only have been hit by rvalue, <em>borrowed</em>, non-view ranges. Before the adoption of <span class="citation" data-cites="P2325R3">[<a href="#ref-P2325R3" role="doc-biblioref">P2325R3</a>]</span>, fixed-extent <code class="sourceCode cpp">span</code> was the pub quiz trivia answer to what this bullet was for. Afterwards, is there a real type that would fit here?<a href="#fnref3" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
</ol>
</section>
</div>
</div>
</body>
</html>