-
Notifications
You must be signed in to change notification settings - Fork 22
/
p2481r1.html
1041 lines (1033 loc) · 101 KB
/
p2481r1.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
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<!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="2022-07-15" />
<title>Forwarding reference to specific type/template</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">Forwarding reference to specific type/template</h1>
<table style="border:none;float:right">
<tr>
<td>Document #:</td>
<td>P2481R1</td>
</tr>
<tr>
<td>Date:</td>
<td>2022-07-15</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>
EWG<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>
</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>
<ul>
<li><a href="#stdtuple-converting-constructor"><span class="toc-section-number">2.1</span> <code class="sourceCode cpp">std<span class="op">::</span>tuple</code> converting constructor<span></span></a></li>
<li><a href="#stdget-for-stdtuple"><span class="toc-section-number">2.2</span> <code class="sourceCode cpp">std<span class="op">::</span>get</code> for <code class="sourceCode cpp">std<span class="op">::</span>tuple</code><span></span></a></li>
<li><a href="#transform-for-stdoptional"><span class="toc-section-number">2.3</span> <code class="sourceCode cpp">transform</code> for <code class="sourceCode cpp">std<span class="op">::</span>optional</code><span></span></a></li>
<li><a href="#view_interface-members"><span class="toc-section-number">2.4</span> <code class="sourceCode cpp">view_interface</code> members<span></span></a></li>
<li><a href="#the-goal"><span class="toc-section-number">2.5</span> The Goal<span></span></a></li>
</ul></li>
<li><a href="#not-a-proposal"><span class="toc-section-number">3</span> Not a proposal<span></span></a>
<ul>
<li><a href="#t-auto"><span class="toc-section-number">3.1</span> <code class="sourceCode cpp">T <span class="kw">auto</span><span class="op">&&</span></code><span></span></a></li>
<li><a href="#t"><span class="toc-section-number">3.2</span> <code class="sourceCode cpp">T<span class="op">&&&</span></code><span></span></a></li>
<li><a href="#constbool"><span class="toc-section-number">3.3</span> <code class="sourceCode cpp"><span class="kw">const</span><span class="op">(</span><span class="dt">bool</span><span class="op">)</span></code><span></span></a></li>
<li><a href="#qualifiers-q"><span class="toc-section-number">3.4</span> <code class="sourceCode cpp">qualifiers Q</code><span></span></a></li>
<li><a href="#circles-approach"><span class="toc-section-number">3.5</span> Circle’s approach<span></span></a></li>
<li><a href="#something-else"><span class="toc-section-number">3.6</span> Something else<span></span></a></li>
</ul></li>
<li><a href="#bibliography"><span class="toc-section-number">4</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="P2481R0">[<a href="#ref-P2481R0" role="doc-biblioref">P2481R0</a>]</span>, added <a href="#circles-approach">Circle’s approach</a> and a choice implementor quote.</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>There are many situations where the goal of a function template is deduce an arbitrary type - an arbitrary range, an arbitrary value, an arbitrary predicate, and so forth. But sometimes, we need something more specific. While we still want to allow for deducing <code class="sourceCode cpp"><span class="kw">const</span></code> vs mutable and lvalue vs rvalue, we know either what concrete type or concrete class template we need - and simply want to deduce <em>just</em> that. With the adoption of <span class="citation" data-cites="P0847R7">[<a href="#ref-P0847R7" role="doc-biblioref">P0847R7</a>]</span>, the incidence of this will only go up.</p>
<p>It may help if I provide a few examples.</p>
<h2 data-number="2.1" id="stdtuple-converting-constructor"><span class="header-section-number">2.1</span> <code class="sourceCode cpp">std<span class="op">::</span>tuple</code> converting constructor<a href="#stdtuple-converting-constructor" class="self-link"></a></h2>
<p><code class="sourceCode cpp">std<span class="op">::</span>tuple<span class="op"><</span>T<span class="op">...></span></code> is constructible from <code class="sourceCode cpp">std<span class="op">::</span>tuple<span class="op"><</span>U<span class="op">...></span> <em>cv</em> <em>ref</em></code> when <code class="sourceCode cpp">T<span class="op">...</span></code> and <code class="sourceCode cpp">U<span class="op">...</span></code> are the same size and each <code class="sourceCode cpp">T</code> is constructible from <code class="sourceCode cpp">U <em>cv</em> <em>ref</em></code> (plus another constraint to avoid clashing with other constructors that I’m just going to ignore for the purposes of this paper). The way this would be written today is:</p>
<blockquote>
<div class="sourceCode" id="cb1"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb1-1"><a href="#cb1-1"></a><span class="kw">template</span> <span class="op"><</span><span class="kw">typename</span><span class="op">...</span> Ts<span class="op">></span></span>
<span id="cb1-2"><a href="#cb1-2"></a><span class="kw">struct</span> tuple <span class="op">{</span></span>
<span id="cb1-3"><a href="#cb1-3"></a> <span class="kw">template</span> <span class="op"><</span><span class="kw">typename</span><span class="op">...</span> Us<span class="op">></span></span>
<span id="cb1-4"><a href="#cb1-4"></a> <span class="kw">requires</span> <span class="kw">sizeof</span><span class="op">...(</span>Ts<span class="op">)</span> <span class="op">==</span> <span class="kw">sizeof</span><span class="op">...(</span>Us<span class="op">)</span></span>
<span id="cb1-5"><a href="#cb1-5"></a> <span class="op">&&</span> <span class="op">(</span>is_constructible_v<span class="op"><</span>Ts, Us<span class="op">&></span> <span class="op">&&</span> <span class="op">...)</span></span>
<span id="cb1-6"><a href="#cb1-6"></a> tuple<span class="op">(</span>tuple<span class="op"><</span>Us<span class="op">...>&)</span>;</span>
<span id="cb1-7"><a href="#cb1-7"></a></span>
<span id="cb1-8"><a href="#cb1-8"></a> <span class="kw">template</span> <span class="op"><</span><span class="kw">typename</span><span class="op">...</span> Us<span class="op">></span></span>
<span id="cb1-9"><a href="#cb1-9"></a> <span class="kw">requires</span> <span class="kw">sizeof</span><span class="op">...(</span>Ts<span class="op">)</span> <span class="op">==</span> <span class="kw">sizeof</span><span class="op">...(</span>Us<span class="op">)</span></span>
<span id="cb1-10"><a href="#cb1-10"></a> <span class="op">&&</span> <span class="op">(</span>is_constructible_v<span class="op"><</span>Ts, Us <span class="kw">const</span><span class="op">&></span> <span class="op">&&</span> <span class="op">...)</span></span>
<span id="cb1-11"><a href="#cb1-11"></a> tuple<span class="op">(</span>tuple<span class="op"><</span>Us<span class="op">...></span> <span class="kw">const</span><span class="op">&)</span>;</span>
<span id="cb1-12"><a href="#cb1-12"></a></span>
<span id="cb1-13"><a href="#cb1-13"></a> <span class="kw">template</span> <span class="op"><</span><span class="kw">typename</span><span class="op">...</span> Us<span class="op">></span></span>
<span id="cb1-14"><a href="#cb1-14"></a> <span class="kw">requires</span> <span class="kw">sizeof</span><span class="op">...(</span>Ts<span class="op">)</span> <span class="op">==</span> <span class="kw">sizeof</span><span class="op">...(</span>Us<span class="op">)</span></span>
<span id="cb1-15"><a href="#cb1-15"></a> <span class="op">&&</span> <span class="op">(</span>is_constructible_v<span class="op"><</span>Ts, Us<span class="op">&&></span> <span class="op">&&</span> <span class="op">...)</span></span>
<span id="cb1-16"><a href="#cb1-16"></a> tuple<span class="op">(</span>tuple<span class="op"><</span>Us<span class="op">...>&&)</span>;</span>
<span id="cb1-17"><a href="#cb1-17"></a></span>
<span id="cb1-18"><a href="#cb1-18"></a> <span class="kw">template</span> <span class="op"><</span><span class="kw">typename</span><span class="op">...</span> Us<span class="op">></span></span>
<span id="cb1-19"><a href="#cb1-19"></a> <span class="kw">requires</span> <span class="kw">sizeof</span><span class="op">...(</span>Ts<span class="op">)</span> <span class="op">==</span> <span class="kw">sizeof</span><span class="op">...(</span>Us<span class="op">)</span></span>
<span id="cb1-20"><a href="#cb1-20"></a> <span class="op">&&</span> <span class="op">(</span>is_constructible_v<span class="op"><</span>Ts, Us <span class="kw">const</span><span class="op">&&></span> <span class="op">&&</span> <span class="op">...)</span></span>
<span id="cb1-21"><a href="#cb1-21"></a> tuple<span class="op">(</span>tuple<span class="op"><</span>Us<span class="op">...></span> <span class="kw">const</span><span class="op">&&)</span>;</span>
<span id="cb1-22"><a href="#cb1-22"></a><span class="op">}</span>;</span></code></pre></div>
</blockquote>
<p>This is pretty tedious to say the least. But it also has a subtle problem: these constructors are all <em>overloads</em> - which means that if the one you’d think would be called is valid, it is still possible for a different one to be invoked. For instance:</p>
<blockquote>
<div class="sourceCode" id="cb2"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb2-1"><a href="#cb2-1"></a><span class="dt">void</span> f<span class="op">(</span>tuple<span class="op"><</span><span class="dt">int</span><span class="op">&>)</span>;</span>
<span id="cb2-2"><a href="#cb2-2"></a><span class="kw">auto</span> g<span class="op">()</span> <span class="op">-></span> tuple<span class="op"><</span><span class="dt">int</span><span class="op">&&></span>;</span>
<span id="cb2-3"><a href="#cb2-3"></a></span>
<span id="cb2-4"><a href="#cb2-4"></a><span class="dt">void</span> h<span class="op">()</span> <span class="op">{</span></span>
<span id="cb2-5"><a href="#cb2-5"></a> f<span class="op">(</span>g<span class="op">())</span>; <span class="co">// ok!</span></span>
<span id="cb2-6"><a href="#cb2-6"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
<p>Here, we’re trying to construct a <code class="sourceCode cpp">tuple<span class="op"><</span><span class="dt">int</span><span class="op">&></span></code> from an <em>rvalue</em> <code class="sourceCode cpp">tuple<span class="op"><</span><span class="dt">int</span><span class="op">&&></span></code>. The desired behavior is that the <code class="sourceCode cpp">tuple<span class="op"><</span>Us<span class="op">...>&&</span></code> is considered and then rejected (because <code class="sourceCode cpp"><span class="dt">int</span><span class="op">&</span></code> is not constructible from <code class="sourceCode cpp">Us<span class="op">&&</span></code> - <code class="sourceCode cpp"><span class="dt">int</span><span class="op">&&</span></code>). That part indeed happens. But the <code class="sourceCode cpp">tuple<span class="op"><</span>Us<span class="op">...></span> <span class="kw">const</span><span class="op">&</span></code> constructor still exists and that one ends up being fine (because <code class="sourceCode cpp"><span class="dt">int</span><span class="op">&</span></code> is constructible from <code class="sourceCode cpp">Us <span class="kw">const</span><span class="op">&</span></code> - which is <code class="sourceCode cpp"><span class="dt">int</span><span class="op">&</span></code> here). That’s surprising and undesirable.</p>
<p>But in order to avoid this, we’d need to only have a single constructor template. What we <em>want</em> is to have <em>some kind</em> of <code class="sourceCode cpp">tuple<span class="op"><</span>Us<span class="op">...></span></code> and just deduce the <code class="sourceCode cpp"><em>cv</em> <em>ref</em></code> part. But our only choice today is either the code above (tedious, yet mostly functional, despite this problem) or to go full template:</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><span class="kw">typename</span><span class="op">...</span> Ts<span class="op">></span></span>
<span id="cb3-2"><a href="#cb3-2"></a><span class="kw">struct</span> tuple <span class="op">{</span></span>
<span id="cb3-3"><a href="#cb3-3"></a> <span class="kw">template</span> <span class="op"><</span><span class="kw">typename</span> Other<span class="op">></span></span>
<span id="cb3-4"><a href="#cb3-4"></a> <span class="kw">requires</span> is_specialization_of<span class="op"><</span>remove_cvref_t<span class="op"><</span>Other<span class="op">></span>, tuple<span class="op">></span></span>
<span id="cb3-5"><a href="#cb3-5"></a> <span class="op">&&</span> <span class="co">/* ???? */</span></span>
<span id="cb3-6"><a href="#cb3-6"></a> tuple<span class="op">(</span>Other<span class="op">&&</span> rhs<span class="op">)</span>;</span>
<span id="cb3-7"><a href="#cb3-7"></a><span class="op">}</span>;</span></code></pre></div>
</blockquote>
<p>How do we write the rest of the constraint? We don’t really have a good way of doing so. Besides, for types which inherit from <code class="sourceCode cpp">std<span class="op">::</span>tuple</code>, this is now actually wrong - that derived type will not be a specialization of tuple, but rather instead inherit from one. We have to do extra work to get that part right, as we currently do in the <code class="sourceCode cpp">std<span class="op">::</span>visit</code> specification - see <span>22.6.7 <a href="https://wg21.link/variant.visit">[variant.visit]</a></span>/1.</p>
<h2 data-number="2.2" id="stdget-for-stdtuple"><span class="header-section-number">2.2</span> <code class="sourceCode cpp">std<span class="op">::</span>get</code> for <code class="sourceCode cpp">std<span class="op">::</span>tuple</code><a href="#stdget-for-stdtuple" class="self-link"></a></h2>
<p>We run into the same thing for non-member functions, where we want to have <code class="sourceCode cpp">std<span class="op">::</span>get<span class="op"><</span>I<span class="op">></span></code> be invocable on every kind of tuple. Which today likewise has to be written:</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><span class="dt">size_t</span> I, <span class="kw">typename</span><span class="op">...</span> Ts<span class="op">></span></span>
<span id="cb4-2"><a href="#cb4-2"></a><span class="kw">auto</span> get<span class="op">(</span>tuple<span class="op"><</span>Ts<span class="op">...>&)</span> <span class="op">-></span> tuple_element_t<span class="op"><</span>I, tuple<span class="op"><</span>Ts<span class="op">...>>&</span>;</span>
<span id="cb4-3"><a href="#cb4-3"></a></span>
<span id="cb4-4"><a href="#cb4-4"></a><span class="kw">template</span> <span class="op"><</span><span class="dt">size_t</span> I, <span class="kw">typename</span><span class="op">...</span> Ts<span class="op">></span></span>
<span id="cb4-5"><a href="#cb4-5"></a><span class="kw">auto</span> get<span class="op">(</span>tuple<span class="op"><</span>Ts<span class="op">...></span> <span class="kw">const</span><span class="op">&)</span> <span class="op">-></span> tuple_element_t<span class="op"><</span>I, tuple<span class="op"><</span>Ts<span class="op">...>></span> <span class="kw">const</span><span class="op">&</span>;</span>
<span id="cb4-6"><a href="#cb4-6"></a></span>
<span id="cb4-7"><a href="#cb4-7"></a><span class="kw">template</span> <span class="op"><</span><span class="dt">size_t</span> I, <span class="kw">typename</span><span class="op">...</span> Ts<span class="op">></span></span>
<span id="cb4-8"><a href="#cb4-8"></a><span class="kw">auto</span> get<span class="op">(</span>tuple<span class="op"><</span>Ts<span class="op">...>&&)</span> <span class="op">-></span> tuple_element_t<span class="op"><</span>I, tuple<span class="op"><</span>Ts<span class="op">...>>&&</span>;</span>
<span id="cb4-9"><a href="#cb4-9"></a></span>
<span id="cb4-10"><a href="#cb4-10"></a><span class="kw">template</span> <span class="op"><</span><span class="dt">size_t</span> I, <span class="kw">typename</span><span class="op">...</span> Ts<span class="op">></span></span>
<span id="cb4-11"><a href="#cb4-11"></a><span class="kw">auto</span> get<span class="op">(</span>tuple<span class="op"><</span>Ts<span class="op">...></span> <span class="kw">const</span><span class="op">&&)</span> <span class="op">-></span> tuple_element_t<span class="op"><</span>I, tuple<span class="op"><</span>Ts<span class="op">...>></span> <span class="kw">const</span><span class="op">&&</span>;</span></code></pre></div>
</blockquote>
<p>This one we could try to rewrite as a single function template, but in order to do that, we need to first coerce the type down to some kind of specialization of <code class="sourceCode cpp">tuple</code> - which ends up requiring a lot of the same work anyway.</p>
<h2 data-number="2.3" id="transform-for-stdoptional"><span class="header-section-number">2.3</span> <code class="sourceCode cpp">transform</code> for <code class="sourceCode cpp">std<span class="op">::</span>optional</code><a href="#transform-for-stdoptional" class="self-link"></a></h2>
<p>The previous two examples want to deduce to some specialization of a class template, this example wants to deduce to a specific type. One of the motivation examples from “deducing <code class="sourceCode cpp"><span class="kw">this</span></code>” was to remove the quadruplication necessary when writing a set of overloads that want to preserve <code class="sourceCode cpp"><span class="kw">const</span></code>-ness and value category. The adoption of <span class="citation" data-cites="P0798R8">[<a href="#ref-P0798R8" role="doc-biblioref">P0798R8</a>]</span> gives us several such examples.</p>
<p>In C++20, we’d write it as:</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">template</span> <span class="op"><</span><span class="kw">typename</span> T<span class="op">></span></span>
<span id="cb5-2"><a href="#cb5-2"></a><span class="kw">struct</span> optional <span class="op">{</span></span>
<span id="cb5-3"><a href="#cb5-3"></a> <span class="kw">template</span> <span class="op"><</span><span class="kw">typename</span> F<span class="op">></span> <span class="kw">constexpr</span> <span class="kw">auto</span> transform<span class="op">(</span>F<span class="op">&&)</span> <span class="op">&</span>;</span>
<span id="cb5-4"><a href="#cb5-4"></a> <span class="kw">template</span> <span class="op"><</span><span class="kw">typename</span> F<span class="op">></span> <span class="kw">constexpr</span> <span class="kw">auto</span> transform<span class="op">(</span>F<span class="op">&&)</span> <span class="kw">const</span><span class="op">&</span>;</span>
<span id="cb5-5"><a href="#cb5-5"></a> <span class="kw">template</span> <span class="op"><</span><span class="kw">typename</span> F<span class="op">></span> <span class="kw">constexpr</span> <span class="kw">auto</span> transform<span class="op">(</span>F<span class="op">&&)</span> <span class="op">&&</span>;</span>
<span id="cb5-6"><a href="#cb5-6"></a> <span class="kw">template</span> <span class="op"><</span><span class="kw">typename</span> F<span class="op">></span> <span class="kw">constexpr</span> <span class="kw">auto</span> transform<span class="op">(</span>F<span class="op">&&)</span> <span class="kw">const</span><span class="op">&&</span>;</span>
<span id="cb5-7"><a href="#cb5-7"></a><span class="op">}</span>;</span></code></pre></div>
</blockquote>
<p>complete with quadruplicating the body. But with deducing this, we might consider writing it as:</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">template</span> <span class="op"><</span><span class="kw">typename</span> T<span class="op">></span></span>
<span id="cb6-2"><a href="#cb6-2"></a><span class="kw">struct</span> optional <span class="op">{</span></span>
<span id="cb6-3"><a href="#cb6-3"></a> <span class="kw">template</span> <span class="op"><</span><span class="kw">typename</span> Self, <span class="kw">typename</span> F<span class="op">></span> <span class="kw">constexpr</span> <span class="kw">auto</span> transform<span class="op">(</span><span class="kw">this</span> Self<span class="op">&&</span>, F<span class="op">&&)</span>;</span>
<span id="cb6-4"><a href="#cb6-4"></a><span class="op">}</span>;</span></code></pre></div>
</blockquote>
<p>But this deduces too much! We don’t want to deduce derived types (which in addition to unnecessary extra template instantiations, can also run into <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p0847r7.html#the-shadowing-mitigation-private-inheritance-problem">shadowing issues</a>). We <em>just</em> want to know what the <code class="sourceCode cpp"><span class="kw">const</span></code>-ness and value category of the <code class="sourceCode cpp">optional</code> are. But the only solution at the moment is to C-style cast your way back down to your own type. And that’s not a particular popular solution, even amongst <a href="https://discourse.llvm.org/t/std-pmr-maturity/62200/17">standard library implementors</a>:</p>
<div class="quote">
<p>FWIW, we’re no longer using explicit object member functions for <code class="sourceCode cpp">std<span class="op">::</span>expected</code>; STL couldn’t stomach the necessary C-style cast without which the feature is not fit for purpose.</p>
</div>
<h2 data-number="2.4" id="view_interface-members"><span class="header-section-number">2.4</span> <code class="sourceCode cpp">view_interface</code> members<a href="#view_interface-members" class="self-link"></a></h2>
<p>Similar to the above, but even more specific, are the members for <code class="sourceCode cpp">view_interface</code> (see <span>26.5.3 <a href="https://wg21.link/view.interface">[view.interface]</a></span>). Currently, we have a bunch of pairs of member functions:</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">template</span> <span class="op"><</span><span class="kw">typename</span> D<span class="op">></span></span>
<span id="cb7-2"><a href="#cb7-2"></a><span class="kw">class</span> view_interface <span class="op">{</span></span>
<span id="cb7-3"><a href="#cb7-3"></a> <span class="kw">constexpr</span> D<span class="op">&</span> derived<span class="op">()</span> <span class="kw">noexcept</span> <span class="op">{</span> <span class="cf">return</span> <span class="kw">static_cast</span><span class="op"><</span>D<span class="op">&>(*</span><span class="kw">this</span><span class="op">)</span>; <span class="op">}</span></span>
<span id="cb7-4"><a href="#cb7-4"></a> <span class="kw">constexpr</span> D <span class="kw">const</span><span class="op">&</span> derived<span class="op">()</span> <span class="kw">const</span> <span class="kw">noexcept</span> <span class="op">{</span> <span class="cf">return</span> <span class="kw">static_cast</span><span class="op"><</span>D <span class="kw">const</span><span class="op">&>(*</span><span class="kw">this</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><span class="kw">public</span><span class="op">:</span></span>
<span id="cb7-7"><a href="#cb7-7"></a> <span class="kw">constexpr</span> <span class="dt">bool</span> empty<span class="op">()</span> <span class="kw">requires</span> forward_range<span class="op"><</span>D<span class="op">></span> <span class="op">{</span></span>
<span id="cb7-8"><a href="#cb7-8"></a> <span class="cf">return</span> ranges<span class="op">::</span>begin<span class="op">(</span>derived<span class="op">())</span> <span class="op">==</span> ranges<span class="op">::</span>end<span class="op">(</span>derived<span class="op">())</span>;</span>
<span id="cb7-9"><a href="#cb7-9"></a> <span class="op">}</span></span>
<span id="cb7-10"><a href="#cb7-10"></a> <span class="kw">constexpr</span> <span class="dt">bool</span> empty<span class="op">()</span> <span class="kw">const</span> <span class="kw">requires</span> forward_range<span class="op"><</span>D <span class="kw">const</span><span class="op">></span> <span class="op">{</span></span>
<span id="cb7-11"><a href="#cb7-11"></a> <span class="cf">return</span> ranges<span class="op">::</span>begin<span class="op">(</span>derived<span class="op">())</span> <span class="op">==</span> ranges<span class="op">::</span>end<span class="op">(</span>derived<span class="op">())</span>;</span>
<span id="cb7-12"><a href="#cb7-12"></a> <span class="op">}</span></span>
<span id="cb7-13"><a href="#cb7-13"></a><span class="op">}</span>;</span></code></pre></div>
</blockquote>
<p>With deducing this, we could write this as a single function template - deducing the self parameter such that it ends up being the derived type. But that’s again deducing way too much, when all we want to do is know if we’re a <code class="sourceCode cpp">D<span class="op">&</span></code> or a <code class="sourceCode cpp">D <span class="kw">const</span><span class="op">&</span></code>. But we can’t deduce just <code class="sourceCode cpp"><span class="kw">const</span></code>-ness.</p>
<h2 data-number="2.5" id="the-goal"><span class="header-section-number">2.5</span> The Goal<a href="#the-goal" class="self-link"></a></h2>
<p>To be more concrete, the goal here is to be able to specify a particular type or a particular class template such that template deduction will <em>just</em> deduce the <code class="sourceCode cpp"><span class="kw">const</span></code>-ness and value category, while also (where relevant) performing a derived-to-base conversion. That is, I want to be able to implement a single function template for <code class="sourceCode cpp">optional<span class="op"><</span>T<span class="op">>::</span>transform</code> such that if I invoke it with an rvalue of type <code class="sourceCode cpp">D</code> that inherits publicly and unambiguously from <code class="sourceCode cpp">optional<span class="op"><</span><span class="dt">int</span><span class="op">></span></code>, the function template will be instantiated with a first parameter of <code class="sourceCode cpp">optional<span class="op"><</span><span class="dt">int</span><span class="op">>&&</span></code> (not <code class="sourceCode cpp">D<span class="op">&&</span></code>).</p>
<h1 data-number="3" style="border-bottom:1px solid #cccccc" id="not-a-proposal"><span class="header-section-number">3</span> Not a proposal<a href="#not-a-proposal" class="self-link"></a></h1>
<p>If you don’t find the above examples and the need for more concrete deduction motivating, then I’m sorry for wasting your time.</p>
<p>If you <em>do</em> find the above examples and the need for more concrete deduction motivating, then I’m sorry that I don’t actually have a solution for you. What I have instead are several example syntaxes that I’ve thought about over the years that are all varying degrees of mediocre. My hope with this paper is that other, more creative, people are equally interesting in coming up with a solution to this problem and can come up with a better syntax for it.</p>
<p>Here are those syntax options. I will, for each option, demonstrate how to implement the <code class="sourceCode cpp">tuple</code> converting constructor, <code class="sourceCode cpp">optional<span class="op">::</span>transform</code>, and <code class="sourceCode cpp">view_interface<span class="op">::</span>empty</code>. I will use the following tools:</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="pp">#define FWD</span><span class="op">(</span>e<span class="op">)</span><span class="pp"> </span><span class="kw">static_cast</span><span class="op"><</span><span class="kw">decltype</span><span class="op">(</span>e<span class="op">)&&>(</span>e<span class="op">)</span></span>
<span id="cb8-2"><a href="#cb8-2"></a></span>
<span id="cb8-3"><a href="#cb8-3"></a><span class="kw">template</span> <span class="op"><</span><span class="dt">bool</span> RV, <span class="kw">typename</span> T<span class="op">></span></span>
<span id="cb8-4"><a href="#cb8-4"></a><span class="kw">using</span> apply_ref <span class="op">=</span> std<span class="op">::</span>conditional_t<span class="op"><</span>RV, T<span class="op">&&</span>, T<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="kw">template</span> <span class="op"><</span><span class="dt">bool</span> C, <span class="kw">typename</span> T<span class="op">></span></span>
<span id="cb8-7"><a href="#cb8-7"></a><span class="kw">using</span> apply_const <span class="op">=</span> std<span class="op">::</span>conditional_t<span class="op"><</span>C, T <span class="kw">const</span>, T<span class="op">></span>;</span>
<span id="cb8-8"><a href="#cb8-8"></a></span>
<span id="cb8-9"><a href="#cb8-9"></a><span class="kw">template</span> <span class="op"><</span><span class="dt">bool</span> C, <span class="dt">bool</span> RV, <span class="kw">typename</span> T<span class="op">></span></span>
<span id="cb8-10"><a href="#cb8-10"></a><span class="kw">using</span> apply_const_ref <span class="op">=</span> apply_ref<span class="op"><</span>RV, apply_const<span class="op"><</span>C, T<span class="op">>></span>;</span>
<span id="cb8-11"><a href="#cb8-11"></a></span>
<span id="cb8-12"><a href="#cb8-12"></a><span class="kw">template</span> <span class="op"><</span><span class="kw">typename</span> T, <span class="kw">typename</span> U<span class="op">></span></span>
<span id="cb8-13"><a href="#cb8-13"></a><span class="kw">using</span> copy_cvref_t <span class="op">=</span> apply_const_ref<span class="op"><</span></span>
<span id="cb8-14"><a href="#cb8-14"></a> is_const_v<span class="op"><</span>remove_reference_t<span class="op"><</span>T<span class="op">>></span>,</span>
<span id="cb8-15"><a href="#cb8-15"></a> <span class="op">!</span>is_lvalue_reference_v<span class="op"><</span>T<span class="op">></span>,</span>
<span id="cb8-16"><a href="#cb8-16"></a> U<span class="op">></span>;</span></code></pre></div>
</blockquote>
<h2 data-number="3.1" id="t-auto"><span class="header-section-number">3.1</span> <code class="sourceCode cpp">T <span class="kw">auto</span><span class="op">&&</span></code><a href="#t-auto" class="self-link"></a></h2>
<p>The principle here is that in the same say that <code class="sourceCode cpp">range <span class="kw">auto</span><span class="op">&&</span></code>is some kind of <code class="sourceCode cpp">range</code>, that <code class="sourceCode cpp"><span class="dt">int</span> <span class="kw">auto</span><span class="op">&&</span></code> is some kind of <code class="sourceCode cpp"><span class="dt">int</span></code>. It kind of makes sense, kind of doesn’t. Depends on how you think about it.</p>
<table>
<tr>
<th>
<code class="sourceCode cpp">tuple</code>
</th>
<td>
<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">template</span> <span class="op"><</span><span class="kw">typename</span><span class="op">...</span> Ts<span class="op">></span></span>
<span id="cb9-2"><a href="#cb9-2"></a><span class="kw">struct</span> tuple <span class="op">{</span></span>
<span id="cb9-3"><a href="#cb9-3"></a> <span class="kw">template</span> <span class="op"><</span><span class="kw">typename</span><span class="op">...</span> Us<span class="op">></span></span>
<span id="cb9-4"><a href="#cb9-4"></a> tuple<span class="op">(</span>tuple<span class="op"><</span>Us<span class="op">...></span> <span class="kw">auto</span><span class="op">&&</span> rhs<span class="op">)</span></span>
<span id="cb9-5"><a href="#cb9-5"></a> <span class="kw">requires</span> <span class="kw">sizeof</span><span class="op">...(</span>Us<span class="op">)</span> <span class="op">==</span> <span class="kw">sizeof</span><span class="op">...(</span>Ts<span class="op">)</span></span>
<span id="cb9-6"><a href="#cb9-6"></a> <span class="op">&&</span> <span class="op">(</span>constructible_from<span class="op"><</span></span>
<span id="cb9-7"><a href="#cb9-7"></a> Ts,</span>
<span id="cb9-8"><a href="#cb9-8"></a> copy_cvref_t<span class="op"><</span><span class="kw">decltype</span><span class="op">(</span>rhs<span class="op">)</span>, Us<span class="op">></span></span>
<span id="cb9-9"><a href="#cb9-9"></a> <span class="op">></span> <span class="op">&&</span> <span class="op">...)</span>;</span>
<span id="cb9-10"><a href="#cb9-10"></a><span class="op">}</span>;</span></code></pre></div>
</td>
</tr>
<tr>
<th>
<code class="sourceCode cpp">optional</code>
</th>
<td>
<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><span class="kw">typename</span> T<span class="op">></span></span>
<span id="cb10-2"><a href="#cb10-2"></a><span class="kw">struct</span> optional <span class="op">{</span></span>
<span id="cb10-3"><a href="#cb10-3"></a> <span class="kw">template</span> <span class="op"><</span><span class="kw">typename</span> F<span class="op">></span></span>
<span id="cb10-4"><a href="#cb10-4"></a> <span class="kw">auto</span> transform<span class="op">(</span><span class="kw">this</span> optional <span class="kw">auto</span><span class="op">&&</span> self, F<span class="op">&&</span> f<span class="op">)</span> <span class="op">{</span></span>
<span id="cb10-5"><a href="#cb10-5"></a> <span class="kw">using</span> U <span class="op">=</span> remove_cv_t<span class="op"><</span>invoke_result_t<span class="op"><</span>F,</span>
<span id="cb10-6"><a href="#cb10-6"></a> <span class="kw">decltype</span><span class="op">(</span>FWD<span class="op">(</span>self<span class="op">).</span>value<span class="op">())></span>;</span>
<span id="cb10-7"><a href="#cb10-7"></a></span>
<span id="cb10-8"><a href="#cb10-8"></a> <span class="cf">if</span> <span class="op">(</span>self<span class="op">)</span> <span class="op">{</span></span>
<span id="cb10-9"><a href="#cb10-9"></a> <span class="cf">return</span> optional<span class="op"><</span>U<span class="op">>(</span>invoke<span class="op">(</span>FWD<span class="op">(</span>f<span class="op">)</span>, FWD<span class="op">(</span>self<span class="op">).</span>value<span class="op">()))</span>;</span>
<span id="cb10-10"><a href="#cb10-10"></a> <span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb10-11"><a href="#cb10-11"></a> <span class="cf">return</span> optional<span class="op"><</span>U<span class="op">>()</span>;</span>
<span id="cb10-12"><a href="#cb10-12"></a> <span class="op">}</span></span>
<span id="cb10-13"><a href="#cb10-13"></a> <span class="op">}</span></span>
<span id="cb10-14"><a href="#cb10-14"></a><span class="op">}</span>;</span></code></pre></div>
</td>
</tr>
<tr>
<th>
<code class="sourceCode cpp">view_interface</code>
</th>
<td>
<div class="sourceCode" id="cb11"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb11-1"><a href="#cb11-1"></a><span class="kw">template</span> <span class="op"><</span><span class="kw">typename</span> D<span class="op">></span></span>
<span id="cb11-2"><a href="#cb11-2"></a><span class="kw">struct</span> view_interface <span class="op">{</span></span>
<span id="cb11-3"><a href="#cb11-3"></a> <span class="kw">constexpr</span> <span class="dt">bool</span> empty<span class="op">(</span><span class="kw">this</span> D <span class="kw">auto</span><span class="op">&</span> self<span class="op">)</span></span>
<span id="cb11-4"><a href="#cb11-4"></a> <span class="kw">requires</span> forward_range<span class="op"><</span><span class="kw">decltype</span><span class="op">(</span>self<span class="op">)></span></span>
<span id="cb11-5"><a href="#cb11-5"></a> <span class="op">{</span></span>
<span id="cb11-6"><a href="#cb11-6"></a> <span class="cf">return</span> ranges<span class="op">::</span>begin<span class="op">(</span>self<span class="op">)</span> <span class="op">==</span> ranges<span class="op">::</span>end<span class="op">(</span>self<span class="op">)</span>;</span>
<span id="cb11-7"><a href="#cb11-7"></a> <span class="op">}</span></span>
<span id="cb11-8"><a href="#cb11-8"></a><span class="op">}</span>;</span></code></pre></div>
</td>
</tr>
</table>
<p>The advantage of this syntax is that it’s concise and lets you do what you need to do.</p>
<p>The disadvantage of this syntax is that the only way you can get the type is by writing <code class="sourceCode cpp"><span class="kw">decltype</span><span class="op">(</span>param<span class="op">)</span></code> - and the only way to can pass through the <code class="sourceCode cpp"><span class="kw">const</span></code>-ness and qualifiers is by grabbing them off of <code class="sourceCode cpp"><span class="kw">decltype</span><span class="op">(</span>param<span class="op">)</span></code>. That’s fine if the type itself is all that is necessary (as it the case for <code class="sourceCode cpp">view_interface</code>) but not so much when you actually need to apply them (as is the case for <code class="sourceCode cpp">tuple</code>). This also means that the only place you can put the <code class="sourceCode cpp"><span class="kw">requires</span></code> clause is after the parameters. Another disadvantage is that the derived-to-base conversion aspect of this makes it inconsistent with what <code class="sourceCode cpp">Concept <span class="kw">auto</span></code> actually means - which is not actually doing any conversion.</p>
<h2 data-number="3.2" id="t"><span class="header-section-number">3.2</span> <code class="sourceCode cpp">T<span class="op">&&&</span></code><a href="#t" class="self-link"></a></h2>
<p>Rather than writing <code class="sourceCode cpp">tuple<span class="op"><</span>U<span class="op">...></span> <span class="kw">auto</span><span class="op">&&</span> rhs</code> we can instead introduce a new kind of reference and spell it <code class="sourceCode cpp">tuple<span class="op"><</span>U<span class="op">...>&&&</span> rhs</code>. This syntactically looks nearly the same as the <code class="sourceCode cpp">T <span class="kw">auto</span><span class="op">&&</span></code> version, so I’m not going to copy it.</p>
<p>If we went this route, we would naturally have to also allow:</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">template</span> <span class="op"><</span><span class="kw">typename</span> T<span class="op">></span> <span class="dt">void</span> f<span class="op">(</span>T<span class="op">&&)</span>; <span class="co">// regular forwarding reference</span></span>
<span id="cb12-2"><a href="#cb12-2"></a><span class="kw">template</span> <span class="op"><</span><span class="kw">typename</span> T<span class="op">></span> <span class="dt">void</span> g<span class="op">(</span>T<span class="op">&&&)</span>; <span class="co">// also regular forwarding reference</span></span></code></pre></div>
</blockquote>
<p>The advantage here is that it’s less arguably broken than the previous version, since it’s more reasonable that the <code class="sourceCode cpp">tuple<span class="op"><</span>U<span class="op">...>&&&</span></code> syntax would allow derived-to-base conversion.</p>
<p>The disadvantages are all the other disadvantages of the previous version, plus also a whole new reference token? Swell.</p>
<h2 data-number="3.3" id="constbool"><span class="header-section-number">3.3</span> <code class="sourceCode cpp"><span class="kw">const</span><span class="op">(</span><span class="dt">bool</span><span class="op">)</span></code><a href="#constbool" class="self-link"></a></h2>
<p>We have <code class="sourceCode cpp"><span class="kw">noexcept</span><span class="op">(</span><span class="kw">true</span><span class="op">)</span></code> and <code class="sourceCode cpp"><span class="kw">explicit</span><span class="op">(</span><span class="kw">true</span><span class="op">)</span></code>. What about <code class="sourceCode cpp"><span class="kw">const</span><span class="op">(</span><span class="kw">true</span><span class="op">)</span></code>?</p>
<p>On some level, this seems to make perfect sense. At least for <code class="sourceCode cpp"><span class="kw">const</span></code> - since we want to deduce either <code class="sourceCode cpp">T</code> or <code class="sourceCode cpp">T <span class="kw">const</span></code>, and so <code class="sourceCode cpp"><span class="kw">const</span></code> is either absent or present. But what about value category? How do you represent <code class="sourceCode cpp">T<span class="op">&</span></code> vs <code class="sourceCode cpp">T<span class="op">&&</span></code>? Surely, we wouldn’t do <code class="sourceCode cpp">T <span class="op">&(</span>LV<span class="op">)</span> <span class="op">&&(</span>RV<span class="op">)</span></code> for deducing two different <code class="sourceCode cpp"><span class="dt">bool</span></code>s - these two cases are mutually exclusive. Keeping one of the <code class="sourceCode cpp"><span class="op">&</span></code>s around, as in <code class="sourceCode cpp">T<span class="op">&</span> <span class="op">&(</span>RV<span class="op">)</span></code> (with a mandatory space) also seems pretty bad. So for the purposes of this section, let’s try <code class="sourceCode cpp">T <span class="op">&&</span> <span class="op">(</span>RV<span class="op">)</span></code> (where <code class="sourceCode cpp">RV</code> is <code class="sourceCode cpp"><span class="kw">true</span></code> for rvalues and <code class="sourceCode cpp"><span class="kw">false</span></code> for lvalues, but still a forwarding reference).</p>
<table>
<tr>
<th>
<code class="sourceCode cpp">tuple</code>
</th>
<td>
<div class="sourceCode" id="cb13"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb13-1"><a href="#cb13-1"></a><span class="kw">template</span> <span class="op"><</span><span class="kw">typename</span><span class="op">...</span> Ts<span class="op">></span></span>
<span id="cb13-2"><a href="#cb13-2"></a><span class="kw">struct</span> tuple <span class="op">{</span></span>
<span id="cb13-3"><a href="#cb13-3"></a> <span class="kw">template</span> <span class="op"><</span><span class="kw">typename</span><span class="op">...</span> Us, <span class="dt">bool</span> C, <span class="dt">bool</span> RV<span class="op">></span></span>
<span id="cb13-4"><a href="#cb13-4"></a> <span class="kw">requires</span> <span class="kw">sizeof</span><span class="op">...(</span>Us<span class="op">)</span> <span class="op">==</span> <span class="kw">sizeof</span><span class="op">...(</span>Ts<span class="op">)</span></span>
<span id="cb13-5"><a href="#cb13-5"></a> <span class="op">&&</span> <span class="op">(</span>constructible_from<span class="op"><</span></span>
<span id="cb13-6"><a href="#cb13-6"></a> Ts,</span>
<span id="cb13-7"><a href="#cb13-7"></a> apply_const_ref<span class="op"><</span>C, RV, Us<span class="op">></span></span>
<span id="cb13-8"><a href="#cb13-8"></a> <span class="op">></span> <span class="op">&&</span> <span class="op">...)</span></span>
<span id="cb13-9"><a href="#cb13-9"></a> tuple<span class="op">(</span>tuple<span class="op"><</span>Us<span class="op">...></span> <span class="kw">const</span><span class="op">(</span>C<span class="op">)</span> <span class="op">&&(</span>RV<span class="op">)</span> rhs<span class="op">)</span>;</span>
<span id="cb13-10"><a href="#cb13-10"></a><span class="op">}</span>;</span></code></pre></div>
</td>
</tr>
<tr>
<th>
<code class="sourceCode cpp">optional</code>
</th>
<td>
<div class="sourceCode" id="cb14"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb14-1"><a href="#cb14-1"></a><span class="kw">template</span> <span class="op"><</span><span class="kw">typename</span> T<span class="op">></span></span>
<span id="cb14-2"><a href="#cb14-2"></a><span class="kw">struct</span> optional <span class="op">{</span></span>
<span id="cb14-3"><a href="#cb14-3"></a> <span class="kw">template</span> <span class="op"><</span><span class="kw">typename</span> F, <span class="dt">bool</span> C, <span class="dt">bool</span> RV<span class="op">></span></span>
<span id="cb14-4"><a href="#cb14-4"></a> <span class="kw">auto</span> transform<span class="op">(</span><span class="kw">this</span> optional <span class="kw">const</span><span class="op">(</span>C<span class="op">)</span> <span class="op">&&(</span>RV<span class="op">)</span> self, F<span class="op">&&</span> f<span class="op">)</span> <span class="op">{</span></span>
<span id="cb14-5"><a href="#cb14-5"></a> <span class="kw">using</span> U <span class="op">=</span> remove_cv_t<span class="op"><</span>invoke_result_t<span class="op"><</span>F,</span>
<span id="cb14-6"><a href="#cb14-6"></a> <span class="co">// apply_const_ref<C, RV, T></span></span>
<span id="cb14-7"><a href="#cb14-7"></a> <span class="kw">decltype</span><span class="op">(</span>FWD<span class="op">(</span>self<span class="op">).</span>value<span class="op">())></span>;</span>
<span id="cb14-8"><a href="#cb14-8"></a></span>
<span id="cb14-9"><a href="#cb14-9"></a> <span class="cf">if</span> <span class="op">(</span>self<span class="op">)</span> <span class="op">{</span></span>
<span id="cb14-10"><a href="#cb14-10"></a> <span class="cf">return</span> optional<span class="op"><</span>U<span class="op">>(</span>invoke<span class="op">(</span>FWD<span class="op">(</span>f<span class="op">)</span>, FWD<span class="op">(</span>self<span class="op">).</span>value<span class="op">()))</span>;</span>
<span id="cb14-11"><a href="#cb14-11"></a> <span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb14-12"><a href="#cb14-12"></a> <span class="cf">return</span> optional<span class="op"><</span>U<span class="op">>()</span>;</span>
<span id="cb14-13"><a href="#cb14-13"></a> <span class="op">}</span></span>
<span id="cb14-14"><a href="#cb14-14"></a> <span class="op">}</span></span>
<span id="cb14-15"><a href="#cb14-15"></a><span class="op">}</span>;</span></code></pre></div>
</td>
</tr>
<tr>
<th>
<code class="sourceCode cpp">view_interface</code>
</th>
<td>
<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">typename</span> D<span class="op">></span></span>
<span id="cb15-2"><a href="#cb15-2"></a><span class="kw">struct</span> view_interface <span class="op">{</span></span>
<span id="cb15-3"><a href="#cb15-3"></a> <span class="kw">template</span> <span class="op"><</span><span class="dt">bool</span> C<span class="op">></span></span>
<span id="cb15-4"><a href="#cb15-4"></a> <span class="kw">requires</span> forward_range<span class="op"><</span>apply_const<span class="op"><</span>C, D<span class="op">>></span></span>
<span id="cb15-5"><a href="#cb15-5"></a> <span class="kw">constexpr</span> <span class="dt">bool</span> empty<span class="op">(</span><span class="kw">this</span> D <span class="dt">bool</span><span class="op">(</span>C<span class="op">)&</span> self<span class="op">)</span></span>
<span id="cb15-6"><a href="#cb15-6"></a> <span class="op">{</span></span>
<span id="cb15-7"><a href="#cb15-7"></a> <span class="cf">return</span> ranges<span class="op">::</span>begin<span class="op">(</span>self<span class="op">)</span> <span class="op">==</span> ranges<span class="op">::</span>end<span class="op">(</span>self<span class="op">)</span>;</span>
<span id="cb15-8"><a href="#cb15-8"></a> <span class="op">}</span></span>
<span id="cb15-9"><a href="#cb15-9"></a><span class="op">}</span>;</span></code></pre></div>
</td>
</tr>
</table>
<p>This syntax is… pretty weird. Very weird.</p>
<p>The advantages are that it’s clearer that we’re only deducing <code class="sourceCode cpp"><span class="kw">const</span></code>-ness and ref qualifiers. It also allows you to put <code class="sourceCode cpp"><span class="kw">requires</span></code> clauses after the <em>template-head</em> rather than much later. When only deducing <code class="sourceCode cpp"><span class="kw">const</span></code>, it’s arguably pretty clear what’s going on.</p>
<p>The disadvantages are the obvious weirdness of the syntax, <em>especially</em> for figuring out the value category, and the mandatory metaprogramming around applying those boolean values that we deduce through the types. <code class="sourceCode cpp">apply_const</code> and <code class="sourceCode cpp">apply_const_ref</code> (as I’m arbitrarily calling them here, the former appears as an exposition-only trait in Ranges under the name <code class="sourceCode cpp"><em>maybe-const</em></code>) will be <em>everywhere</em>, and those aren’t exactly obvious to understand either. It may be tempting to allow writing <code class="sourceCode cpp"><span class="dt">int</span> <span class="kw">const</span><span class="op">(</span><span class="kw">false</span><span class="op">)</span> <span class="op">&&(</span><span class="kw">true</span><span class="op">)</span></code> as a type directly to facilitate writing such code (this would be <code class="sourceCode cpp"><span class="dt">int</span><span class="op">&&</span></code>), but this seems facially terrible.</p>
<p>There’s further issues that <code class="sourceCode cpp"><span class="dt">int</span> <span class="kw">const</span><span class="op">(</span><span class="kw">true</span><span class="op">)</span></code> isn’t quite valid grammar today, but it’s pretty close. <code class="sourceCode cpp"><span class="kw">const</span><span class="op">(</span><span class="kw">true</span><span class="op">)</span></code> looks like a cast, and it’s not unreasonable that we may at some point consider <code class="sourceCode cpp"><span class="kw">const</span><span class="op">(</span>x<span class="op">)</span></code> as a language cast version of <code class="sourceCode cpp">std<span class="op">::</span>as_const<span class="op">(</span>x<span class="op">)</span></code>.</p>
<p>But there is one entirely unrelated benefit. Consider trying to write a function that accepts any function pointer:</p>
<blockquote>
<div class="sourceCode" id="cb16"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb16-1"><a href="#cb16-1"></a><span class="kw">template</span> <span class="op"><</span><span class="kw">typename</span> R, <span class="kw">typename</span><span class="op">...</span> Args, <span class="dt">bool</span> B<span class="op">></span></span>
<span id="cb16-2"><a href="#cb16-2"></a><span class="dt">void</span> accepts_function_ptr<span class="op">(</span>R <span class="op">(*</span>p<span class="op">)(</span>Args<span class="op">...)</span> <span class="kw">noexcept</span><span class="op">(</span>B<span class="op">))</span>;</span></code></pre></div>
</blockquote>
<p>That’s all you need (if we ignore varargs, assume the adoption of <span class="citation" data-cites="CWG2355">[<a href="#ref-CWG2355" role="doc-biblioref">CWG2355</a>]</span> - which was accepted but not fully processed yet). And note here the deduction of <code class="sourceCode cpp"><span class="kw">noexcept</span></code>-ness (and the usage of it on a function type) very closely resembles the kind of deduction of <code class="sourceCode cpp"><span class="kw">const</span></code> and value category discussed in this section.</p>
<p>But today if we wanted to deduce a pointer to <em>member</em> function, we have to write a whole lot more - precisely because we can’t deduce all the other stuff at the end of the type:</p>
<blockquote>
<div class="sourceCode" id="cb17"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb17-1"><a href="#cb17-1"></a><span class="co">// this only accepts non-const pointers to member functions that have no ref-qualifier</span></span>
<span id="cb17-2"><a href="#cb17-2"></a><span class="kw">template</span> <span class="op"><</span><span class="kw">typename</span> R, <span class="kw">typename</span> C, <span class="kw">typename</span><span class="op">...</span> Args, <span class="dt">bool</span> B<span class="op">></span></span>
<span id="cb17-3"><a href="#cb17-3"></a><span class="dt">void</span> accepts_member_function_ptr<span class="op">(</span>R <span class="op">(</span>C<span class="op">::*</span>p<span class="op">)(</span>Args<span class="op">...)</span> <span class="kw">noexcept</span><span class="op">(</span>B<span class="op">))</span>;</span>
<span id="cb17-4"><a href="#cb17-4"></a></span>
<span id="cb17-5"><a href="#cb17-5"></a><span class="co">// so we also need this one</span></span>
<span id="cb17-6"><a href="#cb17-6"></a><span class="kw">template</span> <span class="op"><</span><span class="kw">typename</span> R, <span class="kw">typename</span> C, <span class="kw">typename</span><span class="op">...</span> Args, <span class="dt">bool</span> B<span class="op">></span></span>
<span id="cb17-7"><a href="#cb17-7"></a><span class="dt">void</span> accepts_member_function_ptr<span class="op">(</span>R <span class="op">(</span>C<span class="op">::*</span>p<span class="op">)(</span>Args<span class="op">...)</span> <span class="kw">const</span> <span class="kw">noexcept</span><span class="op">(</span>B<span class="op">))</span>;</span>
<span id="cb17-8"><a href="#cb17-8"></a></span>
<span id="cb17-9"><a href="#cb17-9"></a><span class="co">// ... and this one</span></span>
<span id="cb17-10"><a href="#cb17-10"></a><span class="kw">template</span> <span class="op"><</span><span class="kw">typename</span> R, <span class="kw">typename</span> C, <span class="kw">typename</span><span class="op">...</span> Args, <span class="dt">bool</span> B<span class="op">></span></span>
<span id="cb17-11"><a href="#cb17-11"></a><span class="dt">void</span> accepts_member_function_ptr<span class="op">(</span>R <span class="op">(</span>C<span class="op">::*</span>p<span class="op">)(</span>Args<span class="op">...)</span> <span class="op">&</span> <span class="kw">noexcept</span><span class="op">(</span>B<span class="op">))</span>;</span>
<span id="cb17-12"><a href="#cb17-12"></a></span>
<span id="cb17-13"><a href="#cb17-13"></a><span class="co">// ... and also this one</span></span>
<span id="cb17-14"><a href="#cb17-14"></a><span class="kw">template</span> <span class="op"><</span><span class="kw">typename</span> R, <span class="kw">typename</span> C, <span class="kw">typename</span><span class="op">...</span> Args, <span class="dt">bool</span> B<span class="op">></span></span>
<span id="cb17-15"><a href="#cb17-15"></a><span class="dt">void</span> accepts_member_function_ptr<span class="op">(</span>R <span class="op">(</span>C<span class="op">::*</span>p<span class="op">)(</span>Args<span class="op">...)</span> <span class="op">&&</span> <span class="kw">noexcept</span><span class="op">(</span>B<span class="op">))</span>;</span>
<span id="cb17-16"><a href="#cb17-16"></a></span>
<span id="cb17-17"><a href="#cb17-17"></a><span class="co">// ... and then also these two</span></span>
<span id="cb17-18"><a href="#cb17-18"></a><span class="kw">template</span> <span class="op"><</span><span class="kw">typename</span> R, <span class="kw">typename</span> C, <span class="kw">typename</span><span class="op">...</span> Args, <span class="dt">bool</span> B<span class="op">></span></span>
<span id="cb17-19"><a href="#cb17-19"></a><span class="dt">void</span> accepts_member_function_ptr<span class="op">(</span>R <span class="op">(</span>C<span class="op">::*</span>p<span class="op">)(</span>Args<span class="op">...)</span> <span class="kw">const</span><span class="op">&</span> <span class="kw">noexcept</span><span class="op">(</span>B<span class="op">))</span>;</span>
<span id="cb17-20"><a href="#cb17-20"></a></span>
<span id="cb17-21"><a href="#cb17-21"></a><span class="kw">template</span> <span class="op"><</span><span class="kw">typename</span> R, <span class="kw">typename</span> C, <span class="kw">typename</span><span class="op">...</span> Args, <span class="dt">bool</span> B<span class="op">></span></span>
<span id="cb17-22"><a href="#cb17-22"></a><span class="dt">void</span> accepts_member_function_ptr<span class="op">(</span>R <span class="op">(</span>C<span class="op">::*</span>p<span class="op">)(</span>Args<span class="op">...)</span> <span class="kw">const</span><span class="op">&&</span> <span class="kw">noexcept</span><span class="op">(</span>B<span class="op">))</span>;</span></code></pre></div>
</blockquote>
<p>The direction where we can deduce <code class="sourceCode cpp"><span class="kw">const</span></code> in the same way that we can deduce <code class="sourceCode cpp"><span class="kw">noexcept</span></code> provides a much better solution for this. Although here, unlike the examples presented earlier, we’re not simply selecting between <code class="sourceCode cpp"><span class="op">&</span></code> and <code class="sourceCode cpp"><span class="op">&&</span></code>. Here, we have three options. Does that mean a different design then? And what would it look like to handle both cases? It’s a bit unclear.</p>
<h2 data-number="3.4" id="qualifiers-q"><span class="header-section-number">3.4</span> <code class="sourceCode cpp">qualifiers Q</code><a href="#qualifiers-q" class="self-link"></a></h2>
<p>This approach is quite different and involves introducing a new kind of template parameter, which I’m calling <code class="sourceCode cpp">qualifiers</code>, which will deduce an <em>alias template</em>. It may be easier to look at the examples:</p>
<table>
<tr>
<th>
<code class="sourceCode cpp">tuple</code>
</th>
<td>
<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">template</span> <span class="op"><</span><span class="kw">typename</span><span class="op">...</span> Ts<span class="op">></span></span>
<span id="cb18-2"><a href="#cb18-2"></a><span class="kw">struct</span> tuple <span class="op">{</span></span>
<span id="cb18-3"><a href="#cb18-3"></a> <span class="kw">template</span> <span class="op"><</span><span class="kw">typename</span><span class="op">...</span> Us, qualifiers Q<span class="op">></span></span>
<span id="cb18-4"><a href="#cb18-4"></a> <span class="kw">requires</span> <span class="kw">sizeof</span><span class="op">...(</span>Us<span class="op">)</span> <span class="op">==</span> <span class="kw">sizeof</span><span class="op">...(</span>Ts<span class="op">)</span></span>
<span id="cb18-5"><a href="#cb18-5"></a> <span class="op">&&</span> <span class="op">(</span>constructible_from<span class="op"><</span>Ts, Q<span class="op"><</span>Us<span class="op">>></span> <span class="op">&&</span> <span class="op">...)</span></span>
<span id="cb18-6"><a href="#cb18-6"></a> tuple<span class="op">(</span>Q<span class="op"><</span>tuple<span class="op"><</span>Us<span class="op">...>></span> rhs<span class="op">)</span>;</span>
<span id="cb18-7"><a href="#cb18-7"></a><span class="op">}</span>;</span></code></pre></div>
</td>
</tr>
<tr>
<th>
<code class="sourceCode cpp">optional</code>
</th>
<td>
<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">template</span> <span class="op"><</span><span class="kw">typename</span> T<span class="op">></span></span>
<span id="cb19-2"><a href="#cb19-2"></a><span class="kw">struct</span> optional <span class="op">{</span></span>
<span id="cb19-3"><a href="#cb19-3"></a> <span class="kw">template</span> <span class="op"><</span><span class="kw">typename</span> F, qualifiers Q<span class="op">></span></span>
<span id="cb19-4"><a href="#cb19-4"></a> <span class="kw">auto</span> transform<span class="op">(</span><span class="kw">this</span> Q<span class="op"><</span>optional<span class="op">></span> self, F<span class="op">&&</span> f<span class="op">)</span> <span class="op">{</span></span>
<span id="cb19-5"><a href="#cb19-5"></a> <span class="kw">using</span> U <span class="op">=</span> remove_cv_t<span class="op"><</span>invoke_result_t<span class="op"><</span>F, Q<span class="op"><</span>T<span class="op">>>></span>;</span>
<span id="cb19-6"><a href="#cb19-6"></a></span>
<span id="cb19-7"><a href="#cb19-7"></a> <span class="cf">if</span> <span class="op">(</span>self<span class="op">)</span> <span class="op">{</span></span>
<span id="cb19-8"><a href="#cb19-8"></a> <span class="cf">return</span> optional<span class="op"><</span>U<span class="op">>(</span>invoke<span class="op">(</span>FWD<span class="op">(</span>f<span class="op">)</span>, FWD<span class="op">(</span>self<span class="op">).</span>value<span class="op">()))</span>;</span>
<span id="cb19-9"><a href="#cb19-9"></a> <span class="op">}</span> <span class="cf">else</span> <span class="op">{</span></span>
<span id="cb19-10"><a href="#cb19-10"></a> <span class="cf">return</span> optional<span class="op"><</span>U<span class="op">>()</span>;</span>
<span id="cb19-11"><a href="#cb19-11"></a> <span class="op">}</span></span>
<span id="cb19-12"><a href="#cb19-12"></a> <span class="op">}</span></span>
<span id="cb19-13"><a href="#cb19-13"></a><span class="op">}</span>;</span></code></pre></div>
</td>
</tr>
<tr>
<th>
<code class="sourceCode cpp">view_interface</code>
</th>
<td>
<div class="sourceCode" id="cb20"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb20-1"><a href="#cb20-1"></a><span class="kw">template</span> <span class="op"><</span><span class="kw">typename</span> D<span class="op">></span></span>
<span id="cb20-2"><a href="#cb20-2"></a><span class="kw">struct</span> view_interface <span class="op">{</span></span>
<span id="cb20-3"><a href="#cb20-3"></a> <span class="kw">template</span> <span class="op"><</span>qualifiers Q<span class="op">></span></span>
<span id="cb20-4"><a href="#cb20-4"></a> <span class="kw">requires</span> forward_range<span class="op"><</span>Q<span class="op"><</span>D<span class="op">>></span></span>
<span id="cb20-5"><a href="#cb20-5"></a> <span class="kw">constexpr</span> <span class="dt">bool</span> empty<span class="op">(</span><span class="kw">this</span> Q<span class="op"><</span>D<span class="op">>&</span> self<span class="op">)</span></span>
<span id="cb20-6"><a href="#cb20-6"></a> <span class="op">{</span></span>
<span id="cb20-7"><a href="#cb20-7"></a> <span class="cf">return</span> ranges<span class="op">::</span>begin<span class="op">(</span>self<span class="op">)</span> <span class="op">==</span> ranges<span class="op">::</span>end<span class="op">(</span>self<span class="op">)</span>;</span>
<span id="cb20-8"><a href="#cb20-8"></a> <span class="op">}</span></span>
<span id="cb20-9"><a href="#cb20-9"></a><span class="op">}</span>;</span></code></pre></div>
</td>
</tr>
</table>
<p>The idea here is that a parameter of the form <code class="sourceCode cpp">Q<span class="op"><</span>T<span class="op">></span> x</code> will deduce <code class="sourceCode cpp">T</code> and <code class="sourceCode cpp">Q</code> separately, but <code class="sourceCode cpp">Q</code> will be deduced as one of the following four alias templates:</p>
<ul>
<li><code class="sourceCode cpp"><span class="kw">template</span> <span class="op"><</span><span class="kw">typename</span> T<span class="op">></span> <span class="kw">using</span> Q <span class="op">=</span> T<span class="op">&</span>;</code></li>
<li><code class="sourceCode cpp"><span class="kw">template</span> <span class="op"><</span><span class="kw">typename</span> T<span class="op">></span> <span class="kw">using</span> Q <span class="op">=</span> T <span class="kw">const</span><span class="op">&</span>;</code></li>
<li><code class="sourceCode cpp"><span class="kw">template</span> <span class="op"><</span><span class="kw">typename</span> T<span class="op">></span> <span class="kw">using</span> Q <span class="op">=</span> T<span class="op">&&</span>;</code></li>
<li><code class="sourceCode cpp"><span class="kw">template</span> <span class="op"><</span><span class="kw">typename</span> T<span class="op">></span> <span class="kw">using</span> Q <span class="op">=</span> T <span class="kw">const</span><span class="op">&&</span>;</code></li>
</ul>
<p>Whereas a parameter of the form <code class="sourceCode cpp">Q<span class="op"><</span>T<span class="op">>&</span> x</code> or <code class="sourceCode cpp">Q<span class="op"><</span>T<span class="op">>&&</span></code> will deduce <code class="sourceCode cpp">Q</code> either as:</p>
<ul>
<li><code class="sourceCode cpp"><span class="kw">template</span> <span class="op"><</span><span class="kw">typename</span> T<span class="op">></span> <span class="kw">using</span> Q <span class="op">=</span> T;</code></li>
<li><code class="sourceCode cpp"><span class="kw">template</span> <span class="op"><</span><span class="kw">typename</span> T<span class="op">></span> <span class="kw">using</span> Q <span class="op">=</span> T <span class="kw">const</span>;</code></li>
</ul>
<p>The significant advantage here is that applying the <code class="sourceCode cpp"><span class="kw">const</span></code> and reference qualifiers that we just deduced is trivial, since we already have exactly the tool we need to do that: <code class="sourceCode cpp">Q</code>. This makes all the implementations simpler. It also gives you a way to name the parameter other than <code class="sourceCode cpp"><span class="kw">decltype</span><span class="op">(</span>param<span class="op">)</span></code>, since there is a proper C++ spelling for the parameter itself in all cases.</p>
<p>The disadvantage is that this is <em>quite</em> novel for C++, and extremely weird. Even more dramatically weird than the other two solutions. And that’s even with using the nice name of <code class="sourceCode cpp">qualifiers</code>, which is probably untenable (although <code class="sourceCode cpp">cvrefquals</code> or <code class="sourceCode cpp">refqual</code> might be available?). Also <code class="sourceCode cpp">Q<span class="op"><</span>T<span class="op">></span> x</code> does not look like a forwarding reference, but since <code class="sourceCode cpp">Q<span class="op"><</span>T<span class="op">>&</span> x</code> is the only meaningful way to deduce just <code class="sourceCode cpp"><span class="kw">const</span></code> - this suggests that <code class="sourceCode cpp">Q<span class="op"><</span>T<span class="op">>&&</span> x</code> <em>also</em> needs to deduce just <code class="sourceCode cpp"><span class="kw">const</span></code> (even though why would anyone write this), which leaves <code class="sourceCode cpp">Q<span class="op"><</span>T<span class="op">></span> x</code> alone.</p>
<p>There’s also the question of how we could provide an explicit template argument for <code class="sourceCode cpp">Q</code>. Perhaps that’s spelled <code class="sourceCode cpp">qualifiers<span class="op">::</span>rvalue</code> (to add <code class="sourceCode cpp"><span class="op">&&</span></code>) or <code class="sourceCode cpp">qualifiers<span class="op">::</span>const_lvalue</code> (to add <code class="sourceCode cpp"><span class="kw">const</span><span class="op">&</span></code>) and the like? There’d need to be some language magic way of spelling such a thing - since we probably wouldn’t want to just allow an arbitrary alias template. <code class="sourceCode cpp">std<span class="op">::</span>add_pointer_t</code>, for instance, would suddenly introduce a non-deduced context, and wouldn’t make any sense anyway.</p>
<h2 data-number="3.5" id="circles-approach"><span class="header-section-number">3.5</span> Circle’s approach<a href="#circles-approach" class="self-link"></a></h2>
<p>Sean Baxter implemented the following approach in Circle:</p>
<blockquote>
<div class="sourceCode" id="cb21"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb21-1"><a href="#cb21-1"></a><span class="kw">template</span><span class="op"><</span><span class="kw">typename</span> T, <span class="kw">typename</span><span class="op">...</span> Args<span class="op">></span></span>
<span id="cb21-2"><a href="#cb21-2"></a><span class="dt">void</span> f<span class="op">(</span>T<span class="op">&&</span> y <span class="op">:</span> std<span class="op">::</span>tuple<span class="op"><</span>Args<span class="op">...>)</span>;</span></code></pre></div>
</blockquote>
<p>In this syntax, we effectively are deducing some kind of <code class="sourceCode cpp">std<span class="op">::</span>tuple<span class="op"><</span>Args<span class="op">...></span></code>. <code class="sourceCode cpp">T</code> here is always a (possibly reference to) (possibly const) <code class="sourceCode cpp">std<span class="op">::</span>tuple</code>. This behaves the same way as the previous section’s:</p>
<blockquote>
<div class="sourceCode" id="cb22"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb22-1"><a href="#cb22-1"></a><span class="kw">template</span><span class="op"><</span>qualifiers Q, <span class="kw">typename</span><span class="op">...</span> Args<span class="op">></span></span>
<span id="cb22-2"><a href="#cb22-2"></a><span class="dt">void</span> f<span class="op">(</span>Q<span class="op"><</span>std<span class="op">::</span>tuple<span class="op"><</span>Args<span class="op">...>></span> y<span class="op">)</span>;</span></code></pre></div>
</blockquote>
<p>with the only difference being what additional information you have available to you: whether that’s the type of <code class="sourceCode cpp">y</code> (<code class="sourceCode cpp">T</code>, or really <code class="sourceCode cpp">T<span class="op">&&</span></code>) or an alias providing the appropriate qualifiers (<code class="sourceCode cpp">Q</code>). As such, their uses are broadly similar:</p>
<table>
<thead>
<tr class="header">
<th><div style="text-align:center">
<strong>Qualifiers</strong>
</div></th>
<th><div style="text-align:center">
<strong>Circle</strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><div class="sourceCode" id="cb23"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb23-1"><a href="#cb23-1"></a><span class="kw">template</span> <span class="op"><</span><span class="kw">typename</span><span class="op">...</span> Ts<span class="op">></span></span>
<span id="cb23-2"><a href="#cb23-2"></a><span class="kw">struct</span> tuple <span class="op">{</span></span>
<span id="cb23-3"><a href="#cb23-3"></a> <span class="kw">template</span> <span class="op"><</span><span class="kw">typename</span><span class="op">...</span> Us, qualifiers Q<span class="op">></span></span>
<span id="cb23-4"><a href="#cb23-4"></a> <span class="kw">requires</span> <span class="kw">sizeof</span><span class="op">...(</span>Us<span class="op">)</span> <span class="op">==</span> <span class="kw">sizeof</span><span class="op">...(</span>Ts<span class="op">)</span></span>
<span id="cb23-5"><a href="#cb23-5"></a> <span class="op">&&</span> <span class="op">(</span>constructible_from<span class="op"><</span>Ts, Q<span class="op"><</span>Us<span class="op">>></span> <span class="op">&&</span> <span class="op">...)</span></span>
<span id="cb23-6"><a href="#cb23-6"></a> tuple<span class="op">(</span>Q<span class="op"><</span>tuple<span class="op"><</span>Us<span class="op">...>></span> rhs<span class="op">)</span>;</span>
<span id="cb23-7"><a href="#cb23-7"></a><span class="op">}</span>;</span></code></pre></div></td>
<td><div class="sourceCode" id="cb24"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb24-1"><a href="#cb24-1"></a><span class="kw">template</span> <span class="op"><</span><span class="kw">typename</span><span class="op">...</span> Ts<span class="op">></span></span>
<span id="cb24-2"><a href="#cb24-2"></a><span class="kw">struct</span> tuple <span class="op">{</span></span>
<span id="cb24-3"><a href="#cb24-3"></a> <span class="kw">template</span> <span class="op"><</span><span class="kw">typename</span><span class="op">...</span> Us, <span class="kw">typename</span> Rhs<span class="op">></span></span>
<span id="cb24-4"><a href="#cb24-4"></a> <span class="kw">requires</span> <span class="kw">sizeof</span><span class="op">...(</span>Us<span class="op">)</span> <span class="op">==</span> <span class="kw">sizeof</span><span class="op">...(</span>Ts<span class="op">)</span></span>
<span id="cb24-5"><a href="#cb24-5"></a> <span class="op">&&</span> <span class="op">(</span>constructible_from<span class="op"><</span>Ts, copy_cvref_t<span class="op"><</span>Rhs, Us<span class="op">>></span> <span class="op">&&</span> <span class="op">...)</span></span>
<span id="cb24-6"><a href="#cb24-6"></a> tuple<span class="op">(</span>Rhs<span class="op">&&</span> rhs <span class="op">:</span> tuple<span class="op"><</span>Us<span class="op">...>)</span>;</span>
<span id="cb24-7"><a href="#cb24-7"></a><span class="op">}</span>;</span></code></pre></div></td>
</tr>
<tr class="even">
<td><div class="sourceCode" id="cb25"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb25-1"><a href="#cb25-1"></a><span class="kw">template</span> <span class="op"><</span><span class="kw">typename</span> D<span class="op">></span></span>
<span id="cb25-2"><a href="#cb25-2"></a><span class="kw">struct</span> view_interface <span class="op">{</span></span>
<span id="cb25-3"><a href="#cb25-3"></a> <span class="kw">template</span> <span class="op"><</span>qualifiers Q<span class="op">></span></span>
<span id="cb25-4"><a href="#cb25-4"></a> <span class="kw">requires</span> forward_range<span class="op"><</span>Q<span class="op"><</span>D<span class="op">>></span></span>
<span id="cb25-5"><a href="#cb25-5"></a> <span class="kw">constexpr</span> <span class="dt">bool</span> empty<span class="op">(</span><span class="kw">this</span> Q<span class="op"><</span>D<span class="op">>&</span> self<span class="op">)</span></span>
<span id="cb25-6"><a href="#cb25-6"></a> <span class="op">{</span></span>
<span id="cb25-7"><a href="#cb25-7"></a> <span class="cf">return</span> ranges<span class="op">::</span>begin<span class="op">(</span>self<span class="op">)</span> <span class="op">==</span> ranges<span class="op">::</span>end<span class="op">(</span>self<span class="op">)</span>;</span>