-
Notifications
You must be signed in to change notification settings - Fork 22
/
p1170r0.html
executable file
·1618 lines (1426 loc) · 92.9 KB
/
p1170r0.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
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Overload sets as function parameters</title>
<style type="text/css">html {
position: relative;
max-width: 1024px;
height: 100%;
}
body {
font-family: Helvetica, arial, sans-serif;
font-size: 14px;
line-height: 1.6;
padding-top: 10px;
padding-bottom: 10px;
background-color: white;
padding: 30px;
}
body>*:first-child {
margin-top: 0 !important;
}
body>*:last-child {
margin-bottom: 0 !important;
}
a {
color: #4183C4;
}
a.absent {
color: #cc0000;
}
a.anchor {
display: block;
padding-left: 30px;
margin-left: -30px;
cursor: pointer;
position: absolute;
top: 0;
left: 0;
bottom: 0;
}
h1, h2, h3, h4, h5, h6 {
margin: 20px 0 10px;
padding: 0;
font-weight: bold;
-webkit-font-smoothing: antialiased;
cursor: text;
position: relative;
}
h1:hover a.anchor, h2:hover a.anchor, h3:hover a.anchor, h4:hover a.anchor, h5:hover a.anchor, h6:hover a.anchor {
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA09pVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoMTMuMCAyMDEyMDMwNS5tLjQxNSAyMDEyLzAzLzA1OjIxOjAwOjAwKSAgKE1hY2ludG9zaCkiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6OUM2NjlDQjI4ODBGMTFFMTg1ODlEODNERDJBRjUwQTQiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6OUM2NjlDQjM4ODBGMTFFMTg1ODlEODNERDJBRjUwQTQiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo5QzY2OUNCMDg4MEYxMUUxODU4OUQ4M0REMkFGNTBBNCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo5QzY2OUNCMTg4MEYxMUUxODU4OUQ4M0REMkFGNTBBNCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PsQhXeAAAABfSURBVHjaYvz//z8DJYCRUgMYQAbAMBQIAvEqkBQWXI6sHqwHiwG70TTBxGaiWwjCTGgOUgJiF1J8wMRAIUA34B4Q76HUBelAfJYSA0CuMIEaRP8wGIkGMA54bgQIMACAmkXJi0hKJQAAAABJRU5ErkJggg==) no-repeat 10px center;
text-decoration: none;
}
h1 tt, h1 code {
font-size: inherit;
}
h2 tt, h2 code {
font-size: inherit;
}
h3 tt, h3 code {
font-size: inherit;
}
h4 tt, h4 code {
font-size: inherit;
}
h5 tt, h5 code {
font-size: inherit;
}
h6 tt, h6 code {
font-size: inherit;
}
h1 {
font-size: 28px;
color: black;
}
h2 {
font-size: 24px;
border-bottom: 1px solid #cccccc;
color: black;
}
h3 {
font-size: 18px;
}
h4 {
font-size: 16px;
}
h5 {
font-size: 14px;
}
h6 {
color: #777777;
font-size: 14px;
}
p, blockquote, ol, dl, li, table, pre {
margin: 15px 0;
}
hr {
background: transparent url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAYAAAAECAYAAACtBE5DAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMC1jMDYwIDYxLjEzNDc3NywgMjAxMC8wMi8xMi0xNzozMjowMCAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNSBNYWNpbnRvc2giIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6OENDRjNBN0E2NTZBMTFFMEI3QjRBODM4NzJDMjlGNDgiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6OENDRjNBN0I2NTZBMTFFMEI3QjRBODM4NzJDMjlGNDgiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo4Q0NGM0E3ODY1NkExMUUwQjdCNEE4Mzg3MkMyOUY0OCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo4Q0NGM0E3OTY1NkExMUUwQjdCNEE4Mzg3MkMyOUY0OCIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PqqezsUAAAAfSURBVHjaYmRABcYwBiM2QSA4y4hNEKYDQxAEAAIMAHNGAzhkPOlYAAAAAElFTkSuQmCC) repeat-x 0 0;
border: 0 none;
color: #cccccc;
height: 4px;
padding: 0;
}
body>h2:first-child {
margin-top: 0;
padding-top: 0;
}
body>h1:first-child {
margin-top: 0;
padding-top: 0;
}
body>h1:first-child+h2 {
margin-top: 0;
padding-top: 0;
}
body>h3:first-child, body>h4:first-child, body>h5:first-child, body>h6:first-child {
margin-top: 0;
padding-top: 0;
}
a:first-child h1, a:first-child h2, a:first-child h3, a:first-child h4, a:first-child h5, a:first-child h6 {
margin-top: 0;
padding-top: 0;
}
h1 p, h2 p, h3 p, h4 p, h5 p, h6 p {
margin-top: 0;
}
li p.first {
display: inline-block;
}
li {
margin: 0;
}
ol {
padding-left: 30px;
margin: 5px;
counter-reset: item;
margin-left: -1px;
margin-bottom: -1px;
margin-top: -1px;
}
ol > li {
counter-increment: item;
margin-bottom: -1px;
margin-top: -1px;
}
ol ol > li {
display: block;
margin-bottom: -1px;
margin-top: -1px;
}
ol ol > li:before {
content: counters(item, ".") ". ";
margin-left: -30px;
margin-bottom: -1px;
margin-top: -1px;
}
ul :first-child, ol :first-child {
margin-top: 0;
}
ul ul {
margin-left: -15px;
}
dl {
padding: 0;
}
dl dt {
font-size: 14px;
font-weight: bold;
font-style: italic;
padding: 0;
margin: 15px 0 5px;
}
dl dt:first-child {
padding: 0;
}
dl dt> :first-child {
margin-top: 0;
}
dl dt> :last-child {
margin-bottom: 0;
}
dl dd {
margin: 0 0 15px;
padding: 0 15px;
}
dl dd> :first-child {
margin-top: 0;
}
dl dd> :last-child {
margin-bottom: 0;
}
blockquote {
border-left: 4px solid #dddddd;
padding: 0 15px;
color: #777777;
}
blockquote> :first-child {
margin-top: 0;
}
blockquote> :last-child {
margin-bottom: 0;
}
table {
padding: 0;
border-collapse: collapse;
}
table tr {
border-top: 1px solid #cccccc;
background-color: white;
margin: 0;
padding: 0;
}
table tr:nth-child(2n) {
background-color: #f8f8f8;
}
table tr th {
font-weight: bold;
border: 1px solid #cccccc;
margin: 0;
padding: 6px 13px;
}
table tr td {
border: 1px solid #cccccc;
margin: 0;
padding: 6px 13px;
}
table tr th :first-child, table tr td :first-child {
margin-top: 0;
}
table tr th :last-child, table tr td :last-child {
margin-bottom: 0;
}
td {
vertical-align: top;
}
img {
max-width: 100%;
}
span.frame {
display: block;
overflow: hidden;
}
span.frame>span {
border: 1px solid #dddddd;
display: block;
float: left;
overflow: hidden;
margin: 13px 0 0;
padding: 7px;
width: auto;
}
span.frame span img {
display: block;
float: left;
}
span.frame span span {
clear: both;
color: #333333;
display: block;
padding: 5px 0 0;
}
span.align-center {
display: block;
overflow: hidden;
clear: both;
}
span.align-center>span {
display: block;
overflow: hidden;
margin: 13px auto 0;
text-align: center;
}
span.align-center span img {
margin: 0 auto;
text-align: center;
}
span.align-right {
display: block;
overflow: hidden;
clear: both;
}
span.align-right>span {
display: block;
overflow: hidden;
margin: 13px 0 0;
text-align: right;
}
span.align-right span img {
margin: 0;
text-align: right;
}
span.float-left {
display: block;
margin-right: 13px;
overflow: hidden;
float: left;
}
span.float-left span {
margin: 13px 0 0;
}
span.float-right {
display: block;
margin-left: 13px;
overflow: hidden;
float: right;
}
span.float-right>span {
display: block;
overflow: hidden;
margin: 13px auto 0;
text-align: right;
}
code, tt {
margin: 0 2px;
padding: 0 5px;
white-space: nowrap;
border: 1px solid #eaeaea;
background-color: #f8f8f8;
border-radius: 3px;
}
pre code {
margin: 0;
padding: 0;
white-space: pre;
border: none;
background: transparent;
}
.highlight pre {
background-color: #f8f8f8;
border: 1px solid #cccccc;
font-size: 13px;
line-height: 19px;
overflow: auto;
padding: 6px 10px;
border-radius: 3px;
}
pre {
background-color: #f8f8f8;
border: 1px solid #cccccc;
font-size: 13px;
line-height: 19px;
overflow: auto;
overflow-x: hidden;
overflow-y: hidden;
padding: 6px 10px;
border-radius: 3px;
}
pre code, pre tt {
background-color: transparent;
border: none;
}
sup {
font-size: 0.83em;
vertical-align: super;
line-height: 0;
}
kbd {
display: inline-block;
padding: 3px 5px;
font-size: 11px;
line-height: 10px;
color: #555;
vertical-align: middle;
background-color: #fcfcfc;
border: solid 1px #ccc;
border-bottom-color: #bbb;
border-radius: 3px;
box-shadow: inset 0 -1px 0 #bbb
}
* {
-webkit-print-color-adjust: exact;
}
ins {
color: #00A000
}
del {
color: #A00000
}
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-size: 83%;
}
a.self-link:hover {
opacity: 1;
}
a.self-link::before {
content: "§";
}</style>
<style type="text/css">/* PrismJS 1.15.0
https://prismjs.com/download.html#themes=prism&languages=markup+css+clike+c+cpp&plugins=line-highlight */
/**
* prism.js default theme for JavaScript, CSS and HTML
* Based on dabblet (http://dabblet.com)
* @author Lea Verou
*/
code[class*="language-"],
pre[class*="language-"] {
color: black;
background: none;
text-shadow: 0 1px white;
font-family: Consolas, Monaco, 'Andale Mono', 'Ubuntu Mono', monospace;
text-align: left;
white-space: pre;
word-spacing: normal;
word-break: normal;
word-wrap: normal;
line-height: 1.5;
-moz-tab-size: 4;
-o-tab-size: 4;
tab-size: 4;
-webkit-hyphens: none;
-moz-hyphens: none;
-ms-hyphens: none;
hyphens: none;
}
pre[class*="language-"]::-moz-selection, pre[class*="language-"] ::-moz-selection,
code[class*="language-"]::-moz-selection, code[class*="language-"] ::-moz-selection {
text-shadow: none;
background: #b3d4fc;
}
pre[class*="language-"]::selection, pre[class*="language-"] ::selection,
code[class*="language-"]::selection, code[class*="language-"] ::selection {
text-shadow: none;
background: #b3d4fc;
}
@media print {
code[class*="language-"],
pre[class*="language-"] {
text-shadow: none;
}
}
/* Code blocks */
pre[class*="language-"] {
padding: 1em;
margin: .5em 0;
overflow: auto;
}
:not(pre) > code[class*="language-"],
pre[class*="language-"] {
background: #f8f8f8;
}
/* Inline code */
:not(pre) > code[class*="language-"] {
padding: .1em;
border-radius: .3em;
white-space: normal;
}
.token.comment,
.token.prolog,
.token.doctype,
.token.cdata {
color: slategray;
}
.token.punctuation {
color: #999;
}
.namespace {
opacity: .7;
}
.token.property,
.token.tag,
.token.boolean,
.token.number,
.token.constant,
.token.symbol,
.token.deleted {
color: #905;
}
.token.selector,
.token.attr-name,
.token.string,
.token.char,
.token.builtin,
.token.inserted {
color: #690;
}
.token.operator,
.token.entity,
.token.url,
.language-css .token.string,
.style .token.string {
color: #9a6e3a;
}
.token.atrule,
.token.attr-value,
.token.keyword {
color: #07a;
}
.token.function,
.token.class-name {
color: #DD4A68;
}
.token.regex,
.token.important,
.token.variable {
color: #e90;
}
.token.important,
.token.bold {
font-weight: bold;
}
.token.italic {
font-style: italic;
}
.token.entity {
cursor: help;
}
pre[data-line] {
position: relative;
padding: 1em 0 1em 3em;
}
.line-highlight {
position: absolute;
left: 0;
right: 0;
padding: inherit 0;
margin-top: 1em; /* Same as .prism’s padding-top */
background: hsla(24, 20%, 50%,.08);
background: linear-gradient(to right, hsla(24, 20%, 50%,.1) 70%, hsla(24, 20%, 50%,0));
pointer-events: none;
line-height: inherit;
white-space: pre;
}
.line-highlight:before,
.line-highlight[data-end]:after {
content: attr(data-start);
position: absolute;
top: .4em;
left: .6em;
min-width: 1em;
padding: 0 .5em;
background-color: hsla(24, 20%, 50%,.4);
color: hsl(24, 20%, 95%);
font: bold 65%/1.5 sans-serif;
text-align: center;
vertical-align: .3em;
border-radius: 999px;
text-shadow: none;
box-shadow: 0 1px white;
}
.line-highlight[data-end]:after {
content: attr(data-end);
top: auto;
bottom: .4em;
}
.line-numbers .line-highlight:before,
.line-numbers .line-highlight:after {
content: none;
}
</style>
<script type="text/javascript">/* PrismJS 1.15.0
https://prismjs.com/download.html#themes=prism&languages=markup+css+clike+c+cpp+nasm+rust&plugins=line-highlight */
var _self="undefined"!=typeof window?window:"undefined"!=typeof WorkerGlobalScope&&self instanceof WorkerGlobalScope?self:{},Prism=function(){var e=/\blang(?:uage)?-([\w-]+)\b/i,t=0,n=_self.Prism={manual:_self.Prism&&_self.Prism.manual,disableWorkerMessageHandler:_self.Prism&&_self.Prism.disableWorkerMessageHandler,util:{encode:function(e){return e instanceof r?new r(e.type,n.util.encode(e.content),e.alias):"Array"===n.util.type(e)?e.map(n.util.encode):e.replace(/&/g,"&").replace(/</g,"<").replace(/\u00a0/g," ")},type:function(e){return Object.prototype.toString.call(e).match(/\[object (\w+)\]/)[1]},objId:function(e){return e.__id||Object.defineProperty(e,"__id",{value:++t}),e.__id},clone:function(e,t){var r=n.util.type(e);switch(t=t||{},r){case"Object":if(t[n.util.objId(e)])return t[n.util.objId(e)];var a={};t[n.util.objId(e)]=a;for(var l in e)e.hasOwnProperty(l)&&(a[l]=n.util.clone(e[l],t));return a;case"Array":if(t[n.util.objId(e)])return t[n.util.objId(e)];var a=[];return t[n.util.objId(e)]=a,e.forEach(function(e,r){a[r]=n.util.clone(e,t)}),a}return e}},languages:{extend:function(e,t){var r=n.util.clone(n.languages[e]);for(var a in t)r[a]=t[a];return r},insertBefore:function(e,t,r,a){a=a||n.languages;var l=a[e];if(2==arguments.length){r=arguments[1];for(var i in r)r.hasOwnProperty(i)&&(l[i]=r[i]);return l}var o={};for(var s in l)if(l.hasOwnProperty(s)){if(s==t)for(var i in r)r.hasOwnProperty(i)&&(o[i]=r[i]);o[s]=l[s]}var u=a[e];return a[e]=o,n.languages.DFS(n.languages,function(t,n){n===u&&t!=e&&(this[t]=o)}),o},DFS:function(e,t,r,a){a=a||{};for(var l in e)e.hasOwnProperty(l)&&(t.call(e,l,e[l],r||l),"Object"!==n.util.type(e[l])||a[n.util.objId(e[l])]?"Array"!==n.util.type(e[l])||a[n.util.objId(e[l])]||(a[n.util.objId(e[l])]=!0,n.languages.DFS(e[l],t,l,a)):(a[n.util.objId(e[l])]=!0,n.languages.DFS(e[l],t,null,a)))}},plugins:{},highlightAll:function(e,t){n.highlightAllUnder(document,e,t)},highlightAllUnder:function(e,t,r){var a={callback:r,selector:'code[class*="language-"], [class*="language-"] code, code[class*="lang-"], [class*="lang-"] code'};n.hooks.run("before-highlightall",a);for(var l,i=a.elements||e.querySelectorAll(a.selector),o=0;l=i[o++];)n.highlightElement(l,t===!0,a.callback)},highlightElement:function(t,r,a){for(var l,i,o=t;o&&!e.test(o.className);)o=o.parentNode;o&&(l=(o.className.match(e)||[,""])[1].toLowerCase(),i=n.languages[l]),t.className=t.className.replace(e,"").replace(/\s+/g," ")+" language-"+l,t.parentNode&&(o=t.parentNode,/pre/i.test(o.nodeName)&&(o.className=o.className.replace(e,"").replace(/\s+/g," ")+" language-"+l));var s=t.textContent,u={element:t,language:l,grammar:i,code:s};if(n.hooks.run("before-sanity-check",u),!u.code||!u.grammar)return u.code&&(n.hooks.run("before-highlight",u),u.element.textContent=u.code,n.hooks.run("after-highlight",u)),n.hooks.run("complete",u),void 0;if(n.hooks.run("before-highlight",u),r&&_self.Worker){var g=new Worker(n.filename);g.onmessage=function(e){u.highlightedCode=e.data,n.hooks.run("before-insert",u),u.element.innerHTML=u.highlightedCode,a&&a.call(u.element),n.hooks.run("after-highlight",u),n.hooks.run("complete",u)},g.postMessage(JSON.stringify({language:u.language,code:u.code,immediateClose:!0}))}else u.highlightedCode=n.highlight(u.code,u.grammar,u.language),n.hooks.run("before-insert",u),u.element.innerHTML=u.highlightedCode,a&&a.call(t),n.hooks.run("after-highlight",u),n.hooks.run("complete",u)},highlight:function(e,t,a){var l={code:e,grammar:t,language:a};return n.hooks.run("before-tokenize",l),l.tokens=n.tokenize(l.code,l.grammar),n.hooks.run("after-tokenize",l),r.stringify(n.util.encode(l.tokens),l.language)},matchGrammar:function(e,t,r,a,l,i,o){var s=n.Token;for(var u in r)if(r.hasOwnProperty(u)&&r[u]){if(u==o)return;var g=r[u];g="Array"===n.util.type(g)?g:[g];for(var c=0;c<g.length;++c){var h=g[c],f=h.inside,d=!!h.lookbehind,m=!!h.greedy,p=0,y=h.alias;if(m&&!h.pattern.global){var v=h.pattern.toString().match(/[imuy]*$/)[0];h.pattern=RegExp(h.pattern.source,v+"g")}h=h.pattern||h;for(var b=a,k=l;b<t.length;k+=t[b].length,++b){var w=t[b];if(t.length>e.length)return;if(!(w instanceof s)){if(m&&b!=t.length-1){h.lastIndex=k;var _=h.exec(e);if(!_)break;for(var j=_.index+(d?_[1].length:0),P=_.index+_[0].length,A=b,x=k,O=t.length;O>A&&(P>x||!t[A].type&&!t[A-1].greedy);++A)x+=t[A].length,j>=x&&(++b,k=x);if(t[b]instanceof s)continue;I=A-b,w=e.slice(k,x),_.index-=k}else{h.lastIndex=0;var _=h.exec(w),I=1}if(_){d&&(p=_[1]?_[1].length:0);var j=_.index+p,_=_[0].slice(p),P=j+_.length,N=w.slice(0,j),S=w.slice(P),C=[b,I];N&&(++b,k+=N.length,C.push(N));var E=new s(u,f?n.tokenize(_,f):_,y,_,m);if(C.push(E),S&&C.push(S),Array.prototype.splice.apply(t,C),1!=I&&n.matchGrammar(e,t,r,b,k,!0,u),i)break}else if(i)break}}}}},tokenize:function(e,t){var r=[e],a=t.rest;if(a){for(var l in a)t[l]=a[l];delete t.rest}return n.matchGrammar(e,r,t,0,0,!1),r},hooks:{all:{},add:function(e,t){var r=n.hooks.all;r[e]=r[e]||[],r[e].push(t)},run:function(e,t){var r=n.hooks.all[e];if(r&&r.length)for(var a,l=0;a=r[l++];)a(t)}}},r=n.Token=function(e,t,n,r,a){this.type=e,this.content=t,this.alias=n,this.length=0|(r||"").length,this.greedy=!!a};if(r.stringify=function(e,t,a){if("string"==typeof e)return e;if("Array"===n.util.type(e))return e.map(function(n){return r.stringify(n,t,e)}).join("");var l={type:e.type,content:r.stringify(e.content,t,a),tag:"span",classes:["token",e.type],attributes:{},language:t,parent:a};if(e.alias){var i="Array"===n.util.type(e.alias)?e.alias:[e.alias];Array.prototype.push.apply(l.classes,i)}n.hooks.run("wrap",l);var o=Object.keys(l.attributes).map(function(e){return e+'="'+(l.attributes[e]||"").replace(/"/g,""")+'"'}).join(" ");return"<"+l.tag+' class="'+l.classes.join(" ")+'"'+(o?" "+o:"")+">"+l.content+"</"+l.tag+">"},!_self.document)return _self.addEventListener?(n.disableWorkerMessageHandler||_self.addEventListener("message",function(e){var t=JSON.parse(e.data),r=t.language,a=t.code,l=t.immediateClose;_self.postMessage(n.highlight(a,n.languages[r],r)),l&&_self.close()},!1),_self.Prism):_self.Prism;var a=document.currentScript||[].slice.call(document.getElementsByTagName("script")).pop();return a&&(n.filename=a.src,n.manual||a.hasAttribute("data-manual")||("loading"!==document.readyState?window.requestAnimationFrame?window.requestAnimationFrame(n.highlightAll):window.setTimeout(n.highlightAll,16):document.addEventListener("DOMContentLoaded",n.highlightAll))),_self.Prism}();"undefined"!=typeof module&&module.exports&&(module.exports=Prism),"undefined"!=typeof global&&(global.Prism=Prism);
Prism.languages.markup={comment:/<!--[\s\S]*?-->/,prolog:/<\?[\s\S]+?\?>/,doctype:/<!DOCTYPE[\s\S]+?>/i,cdata:/<!\[CDATA\[[\s\S]*?]]>/i,tag:{pattern:/<\/?(?!\d)[^\s>\/=$<%]+(?:\s+[^\s>\/=]+(?:=(?:("|')(?:\\[\s\S]|(?!\1)[^\\])*\1|[^\s'">=]+))?)*\s*\/?>/i,greedy:!0,inside:{tag:{pattern:/^<\/?[^\s>\/]+/i,inside:{punctuation:/^<\/?/,namespace:/^[^\s>\/:]+:/}},"attr-value":{pattern:/=(?:("|')(?:\\[\s\S]|(?!\1)[^\\])*\1|[^\s'">=]+)/i,inside:{punctuation:[/^=/,{pattern:/(^|[^\\])["']/,lookbehind:!0}]}},punctuation:/\/?>/,"attr-name":{pattern:/[^\s>\/]+/,inside:{namespace:/^[^\s>\/:]+:/}}}},entity:/&#?[\da-z]{1,8};/i},Prism.languages.markup.tag.inside["attr-value"].inside.entity=Prism.languages.markup.entity,Prism.hooks.add("wrap",function(a){"entity"===a.type&&(a.attributes.title=a.content.replace(/&/,"&"))}),Prism.languages.xml=Prism.languages.markup,Prism.languages.html=Prism.languages.markup,Prism.languages.mathml=Prism.languages.markup,Prism.languages.svg=Prism.languages.markup;
Prism.languages.css={comment:/\/\*[\s\S]*?\*\//,atrule:{pattern:/@[\w-]+?.*?(?:;|(?=\s*\{))/i,inside:{rule:/@[\w-]+/}},url:/url\((?:(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1|.*?)\)/i,selector:/[^{}\s][^{};]*?(?=\s*\{)/,string:{pattern:/("|')(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},property:/[-_a-z\xA0-\uFFFF][-\w\xA0-\uFFFF]*(?=\s*:)/i,important:/\B!important\b/i,"function":/[-a-z0-9]+(?=\()/i,punctuation:/[(){};:]/},Prism.languages.css.atrule.inside.rest=Prism.languages.css,Prism.languages.markup&&(Prism.languages.insertBefore("markup","tag",{style:{pattern:/(<style[\s\S]*?>)[\s\S]*?(?=<\/style>)/i,lookbehind:!0,inside:Prism.languages.css,alias:"language-css",greedy:!0}}),Prism.languages.insertBefore("inside","attr-value",{"style-attr":{pattern:/\s*style=("|')(?:\\[\s\S]|(?!\1)[^\\])*\1/i,inside:{"attr-name":{pattern:/^\s*style/i,inside:Prism.languages.markup.tag.inside},punctuation:/^\s*=\s*['"]|['"]\s*$/,"attr-value":{pattern:/.+/i,inside:Prism.languages.css}},alias:"language-css"}},Prism.languages.markup.tag));
Prism.languages.clike={comment:[{pattern:/(^|[^\\])\/\*[\s\S]*?(?:\*\/|$)/,lookbehind:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0,greedy:!0}],string:{pattern:/(["'])(?:\\(?:\r\n|[\s\S])|(?!\1)[^\\\r\n])*\1/,greedy:!0},"class-name":{pattern:/((?:\b(?:class|interface|extends|implements|trait|instanceof|new)\s+)|(?:catch\s+\())[\w.\\]+/i,lookbehind:!0,inside:{punctuation:/[.\\]/}},keyword:/\b(?:if|else|while|do|for|return|in|instanceof|function|new|try|throw|catch|finally|null|break|continue)\b/,"boolean":/\b(?:true|false)\b/,"function":/\w+(?=\()/,number:/\b0x[\da-f]+\b|(?:\b\d+\.?\d*|\B\.\d+)(?:e[+-]?\d+)?/i,operator:/--?|\+\+?|!=?=?|<=?|>=?|==?=?|&&?|\|\|?|\?|\*|\/|~|\^|%/,punctuation:/[{}[\];(),.:]/};
Prism.languages.c=Prism.languages.extend("clike",{keyword:/\b(?:_Alignas|_Alignof|_Atomic|_Bool|_Complex|_Generic|_Imaginary|_Noreturn|_Static_assert|_Thread_local|asm|typeof|inline|auto|break|case|char|const|continue|default|do|double|else|enum|extern|float|for|goto|if|int|long|register|return|short|signed|sizeof|static|struct|switch|typedef|union|unsigned|void|volatile|while)\b/,operator:/>>=?|<<=?|->|([-+&|:])\1|[?:~]|[-+*\/%&|^!=<>]=?/,number:/(?:\b0x[\da-f]+|(?:\b\d+\.?\d*|\B\.\d+)(?:e[+-]?\d+)?)[ful]*/i}),Prism.languages.insertBefore("c","string",{macro:{pattern:/(^\s*)#\s*[a-z]+(?:[^\r\n\\]|\\(?:\r\n|[\s\S]))*/im,lookbehind:!0,alias:"property",inside:{string:{pattern:/(#\s*include\s*)(?:<.+?>|("|')(?:\\?.)+?\2)/,lookbehind:!0},directive:{pattern:/(#\s*)\b(?:define|defined|elif|else|endif|error|ifdef|ifndef|if|import|include|line|pragma|undef|using)\b/,lookbehind:!0,alias:"keyword"}}},constant:/\b(?:__FILE__|__LINE__|__DATE__|__TIME__|__TIMESTAMP__|__func__|EOF|NULL|SEEK_CUR|SEEK_END|SEEK_SET|stdin|stdout|stderr)\b/}),delete Prism.languages.c["class-name"],delete Prism.languages.c["boolean"];
Prism.languages.cpp=Prism.languages.extend("c",{keyword:/\b(?:alignas|alignof|asm|auto|bool|break|case|catch|char|char16_t|char32_t|class|compl|const|constexpr|const_cast|continue|decltype|default|delete|do|double|dynamic_cast|else|enum|explicit|export|extern|float|for|friend|goto|if|inline|int|int8_t|int16_t|int32_t|int64_t|uint8_t|uint16_t|uint32_t|uint64_t|long|mutable|namespace|new|noexcept|nullptr|operator|private|protected|public|register|reinterpret_cast|return|short|signed|sizeof|static|static_assert|static_cast|struct|switch|template|this|thread_local|throw|try|typedef|typeid|typename|union|unsigned|using|virtual|void|volatile|wchar_t|while)\b/,"boolean":/\b(?:true|false)\b/,operator:/>>=?|<<=?|->|([-+&|:])\1|[?:~]|[-+*\/%&|^!=<>]=?|\b(?:and|and_eq|bitand|bitor|not|not_eq|or|or_eq|xor|xor_eq)\b/}),Prism.languages.insertBefore("cpp","keyword",{"class-name":{pattern:/(class\s+)\w+/i,lookbehind:!0}}),Prism.languages.insertBefore("cpp","string",{"raw-string":{pattern:/R"([^()\\ ]{0,16})\([\s\S]*?\)\1"/,alias:"string",greedy:!0}});
Prism.languages.nasm={comment:/;.*$/m,string:/(["'`])(?:\\.|(?!\1)[^\\\r\n])*\1/,label:{pattern:/(^\s*)[A-Za-z._?$][\w.?$@~#]*:/m,lookbehind:!0,alias:"function"},keyword:[/\[?BITS (?:16|32|64)\]?/,{pattern:/(^\s*)section\s*[a-zA-Z.]+:?/im,lookbehind:!0},/(?:extern|global)[^;\r\n]*/i,/(?:CPU|FLOAT|DEFAULT).*$/m],register:{pattern:/\b(?:st\d|[xyz]mm\d\d?|[cdt]r\d|r\d\d?[bwd]?|[er]?[abcd]x|[abcd][hl]|[er]?(?:bp|sp|si|di)|[cdefgs]s)\b/i,alias:"variable"},number:/(?:\b|(?=\$))(?:0[hx][\da-f]*\.?[\da-f]+(?:p[+-]?\d+)?|\d[\da-f]+[hx]|\$\d[\da-f]*|0[oq][0-7]+|[0-7]+[oq]|0[by][01]+|[01]+[by]|0[dt]\d+|\d*\.?\d+(?:\.?e[+-]?\d+)?[dt]?)\b/i,operator:/[\[\]*+\-\/%<>=&|$!]/};
Prism.languages.rust={comment:[{pattern:/(^|[^\\])\/\*[\s\S]*?\*\//,lookbehind:!0},{pattern:/(^|[^\\:])\/\/.*/,lookbehind:!0}],string:[{pattern:/b?r(#*)"(?:\\.|(?!"\1)[^\\\r\n])*"\1/,greedy:!0},{pattern:/b?"(?:\\.|[^\\\r\n"])*"/,greedy:!0}],"char":{pattern:/b?'(?:\\(?:x[0-7][\da-fA-F]|u{(?:[\da-fA-F]_*){1,6}|.)|[^\\\r\n\t'])'/,alias:"string"},"lifetime-annotation":{pattern:/'[^\s>']+/,alias:"symbol"},keyword:/\b(?:abstract|alignof|as|be|box|break|const|continue|crate|do|else|enum|extern|false|final|fn|for|if|impl|in|let|loop|match|mod|move|mut|offsetof|once|override|priv|pub|pure|ref|return|sizeof|static|self|struct|super|true|trait|type|typeof|unsafe|unsized|use|virtual|where|while|yield)\b/,attribute:{pattern:/#!?\[.+?\]/,greedy:!0,alias:"attr-name"},"function":[/\w+(?=\s*\()/,/\w+!(?=\s*\(|\[)/],"macro-rules":{pattern:/\w+!/,alias:"function"},number:/\b(?:0x[\dA-Fa-f](?:_?[\dA-Fa-f])*|0o[0-7](?:_?[0-7])*|0b[01](?:_?[01])*|(\d(?:_?\d)*)?\.?\d(?:_?\d)*(?:[Ee][+-]?\d+)?)(?:_?(?:[iu](?:8|16|32|64)?|f32|f64))?\b/,"closure-params":{pattern:/\|[^|]*\|(?=\s*[{-])/,inside:{punctuation:/[|:,]/,operator:/[&*]/}},punctuation:/[{}[\];(),:]|\.+|->/,operator:/[-+*\/%!^]=?|=[=>]?|@|&[&=]?|\|[|=]?|<<?=?|>>?=?/};
!function(){function e(e,t){return Array.prototype.slice.call((t||document).querySelectorAll(e))}function t(e,t){return t=" "+t+" ",(" "+e.className+" ").replace(/[\n\t]/g," ").indexOf(t)>-1}function n(e,n,i){n="string"==typeof n?n:e.getAttribute("data-line");for(var o,l=n.replace(/\s+/g,"").split(","),a=+e.getAttribute("data-line-offset")||0,s=r()?parseInt:parseFloat,d=s(getComputedStyle(e).lineHeight),u=t(e,"line-numbers"),c=0;o=l[c++];){var p=o.split("-"),m=+p[0],f=+p[1]||m,h=e.querySelector('.line-highlight[data-range="'+o+'"]')||document.createElement("div");if(h.setAttribute("aria-hidden","true"),h.setAttribute("data-range",o),h.className=(i||"")+" line-highlight",u&&Prism.plugins.lineNumbers){var g=Prism.plugins.lineNumbers.getLine(e,m),y=Prism.plugins.lineNumbers.getLine(e,f);g&&(h.style.top=g.offsetTop+"px"),y&&(h.style.height=y.offsetTop-g.offsetTop+y.offsetHeight+"px")}else h.setAttribute("data-start",m),f>m&&h.setAttribute("data-end",f),h.style.top=(m-a-1)*d+"px",h.textContent=new Array(f-m+2).join(" \n");u?e.appendChild(h):(e.querySelector("code")||e).appendChild(h)}}function i(){var t=location.hash.slice(1);e(".temporary.line-highlight").forEach(function(e){e.parentNode.removeChild(e)});var i=(t.match(/\.([\d,-]+)$/)||[,""])[1];if(i&&!document.getElementById(t)){var r=t.slice(0,t.lastIndexOf(".")),o=document.getElementById(r);o&&(o.hasAttribute("data-line")||o.setAttribute("data-line",""),n(o,i,"temporary "),document.querySelector(".temporary.line-highlight").scrollIntoView())}}if("undefined"!=typeof self&&self.Prism&&self.document&&document.querySelector){var r=function(){var e;return function(){if("undefined"==typeof e){var t=document.createElement("div");t.style.fontSize="13px",t.style.lineHeight="1.5",t.style.padding=0,t.style.border=0,t.innerHTML=" <br /> ",document.body.appendChild(t),e=38===t.offsetHeight,document.body.removeChild(t)}return e}}(),o=0;Prism.hooks.add("before-sanity-check",function(t){var n=t.element.parentNode,i=n&&n.getAttribute("data-line");if(n&&i&&/pre/i.test(n.nodeName)){var r=0;e(".line-highlight",n).forEach(function(e){r+=e.textContent.length,e.parentNode.removeChild(e)}),r&&/^( \n)+$/.test(t.code.slice(-r))&&(t.code=t.code.slice(0,-r))}}),Prism.hooks.add("complete",function l(e){var r=e.element.parentNode,a=r&&r.getAttribute("data-line");if(r&&a&&/pre/i.test(r.nodeName)){clearTimeout(o);var s=Prism.plugins.lineNumbers,d=e.plugins&&e.plugins.lineNumbers;t(r,"line-numbers")&&s&&!d?Prism.hooks.add("line-numbers",l):(n(r,a),o=setTimeout(i,1))}}),window.addEventListener("hashchange",i),window.addEventListener("resize",function(){var e=document.querySelectorAll("pre[data-line]");Array.prototype.forEach.call(e,function(e){n(e)})})}}();
</script>
</head>
<body>
<address align=right>
Document Number: P1170R0 <br />
Date: 2018-10-08 <br />
Audience: EWG, LEWG <br />
Reply-To: Barry Revzin, barry dot revzin at gmail dot com<br />Andrew Sutton, asutton at uakron dot edu <br />
</address>
<hr /><h1 align=center><p>Overload sets as function parameters</p></h1>
<h2>Contents</h2>
<div class="toc">
<ol>
<li><a href="#motivation">Motivation</a></li>
<li><a href="#history">History</a></li>
<li><a href="#proposal">Proposal</a><ol>
<li><a href="#implementation-details">Implementation details</a></li>
<li><a href="#constraining-on-overload_set">Constraining on overload_set</a></li>
<li><a href="#deduction-rules">Deduction rules</a><ol>
<li><a href="#deducing-from-an-object">Deducing from an object</a></li>
<li><a href="#deducing-from-a-name-of-a-function">Deducing from a name of a function</a><ol>
<li><a href="#deducing-from-a-name-that-cannot-be-found-by-unqualified-lookup">Deducing from a name that cannot be found by unqualified lookup</a></li>
</ol>
</li>
<li><a href="#deducing-from-partial-class-member-access">Deducing from partial class member access</a></li>
<li><a href="#deducing-from-a-type-member-access">Deducing from a type-member access</a></li>
<li><a href="#deducing-from-an-operator-function-id">Deducing from an operator-function-id</a></li>
<li><a href="#deducing-from-a-type-name">Deducing from a type name</a></li>
<li><a href="#summary-of-deduction-rules">Summary of deduction rules</a></li>
</ol>
</li>
<li><a href="#standard-library-functions-now-and-future">Standard library functions, now and future</a></li>
<li><a href="#alternative-spellings">Alternative spellings</a></li>
<li><a href="#other-potential-avenues">Other potential avenues</a></li>
</ol>
</li>
<li><a href="#acknowledgements">Acknowledgements</a></li>
<li><a href="#references">References</a></li>
</ol>
</div>
<h2 id="motivation">1. Motivation<a class="self-link" href="#motivation"></a></h2>
<p>Calling a function in C++ in pretty fundamental. But abstracting that function call, the most basic generalization, doesn't always work out neatly. </p>
<p>Anytime today that we can write:</p>
<pre class="codehilite"><code class="language-cpp">namespace N {
struct X { ... };
X getX();
}
foo(N::getX()); // for any 'foo'</code></pre>
<p>We might want to also be able to write:</p>
<pre class="codehilite"><code class="language-cpp">template <typename F>
void algorithm(F f, X x) {
f(x);
}
algorithm(foo, N::getX()); // for that same 'foo'</code></pre>
<p>These are, conceptually, very similar. But there are many cases where the former code compiles and runs without issue but the latter fails:</p>
<ol>
<li><code class="language-cpp">foo</code> could be a function that takes default arguments</li>
<li><code class="language-cpp">foo</code> could be a function template</li>
<li><code class="language-cpp">foo</code> could name an overload set</li>
<li><code class="language-cpp">foo</code> could be a function that was only found by ADL</li>
<li><code class="language-cpp">foo</code> in unqualified lookup could have found one function, and so the call to <code class="language-cpp">algorithm()</code> succeeds, but the ADL <code class="language-cpp">foo</code> wasn't found and so the call within <code class="language-cpp">algorithm()</code> fails. Worst case, the <code class="language-cpp">foo</code> found by unqualified lookup is actually a viable candidate, so the wrong function gets called.</li>
<li><code class="language-cpp">foo</code> could be the name of a non-static member function, or non-static member function template, and we are invoking it from within a non-static member function.</li>
<li><code class="language-cpp">foo</code> could be a partial member access, something like <code class="language-cpp">obj.func</code>, which is valid to spell only in the context of invoking the function.</li>
<li><code class="language-cpp">foo</code> could name a function in the standard library, which we are not allowed to take a pointer to (this restriction made more explicit in light of <a href="https://wg21.link/p0551r3" title="Thou Shalt Not Specialize std Function Templates!">P0551</a> and <a href="https://wg21.link/p0921r0" title="Standard Library Compatibility Promises">P0921</a>).</li>
</ol>
<p>The only solution to this problem today, outside of trafficking exclusively in function objects, is to manually wrap <code class="language-cpp">foo</code> in a lambda - and probably be quite vigiliant about doing so:</p>
<pre class="codehilite"><code class="language-cpp">algorithm(getX(), [&](auto&& ...args)
noexcept(noexcept(foo(std::forward<decltype(args)>(args)...)))
-> decltype(foo(std::forward<decltype(args)>(args)...)) {
return foo(std::forward<decltype(args)>(args)...);
});</code></pre>
<p>which is usually seen in the wild in macro form:</p>
<pre class="codehilite"><code class="language-cpp">#define FWD(x) static_cast<decltype(x)&&>(x)
#define RETURNS(expr) noexcept(noexcept(expr)) -> decltype(expr) { return expr; }
#define OVERLOADS_OF(name) [&](auto&& ...args) RETURNS(name(FWD(args)...))
algorithm(getX(), OVERLOADS_OF(foo));</code></pre>
<p>This can be found, for instance, in <a href="http://boost-hof.readthedocs.io/en/latest/include/boost/hof/lift.html" title="BOOST_HOF_LIFT - Boost.HigherOrderFunctions 0.6 documentation">Boost.HOF</a> as <code class="language-cpp">BOOST_HOF_LIFT</code>, and in a recent blog of Andrzej Krzemieński's on <a href="https://akrzemi1.wordpress.com/2018/07/07/functions-in-std/" title="Functions in std | Andrzej's C++ blog">this topic</a>.</p>
<p>However, this is a pretty unsatisfactory solution: we rely on a macro. Or even if not, we have to be vigilant about manually wrapping each and every function at every call site. Why "every"? Because otherwise, we might write code that works today but ends up being very brittle, easily broken. Consider a fairly trivial example:</p>
<pre class="codehilite"><code class="language-cpp+">// some library
void do_something(int );
// some user
std::invoke(do_something, 42);</code></pre>
<p>This works fine today. But the library that provided <code class="language-cpp">do_something</code> might someday wish to make some improvements. Maybe add a defaulted second argument to <code class="language-cpp">do_something</code>. Or a new overload. Or turn <code class="language-cpp">do_something</code> into a function template. Any number of changes that would not change the meaning of code directly invoking <code class="language-cpp">do_something</code> with an <code class="language-cpp">int</code>. The kinds of changes detailed in <a href="https://wg21.link/p0921r0" title="Standard Library Compatibility Promises">P0921</a>. All of these changes would break the above user code - even though it compiles today. So <em>even here</em>, it would be better had the user written:</p>
<pre class="codehilite"><code class="language-cpp">std::invoke(OVERLOADS_OF(do_something), 42);</code></pre>
<p>or, at the very least:</p>
<pre class="codehilite"><code class="language-cpp">std::invoke([](int i){ do_something(i); }, 42);</code></pre>
<p>And that's simply too much to ask of the user - it's too much to have to think about it! We're asking the user to, every time, put a bunch of seemingly unnecessary annotation on every call site. After all, in the context of being invoked by a single argument, these two <em>should be</em> equivalent:</p>
<table>
<tr>
<td>
<pre style="background:transparent;border:0px"><code class="language-cpp">[&](auto&& arg)
noexcept(noexcept(foo(FWD(arg))))
-> decltype(foo(FWD(arg)))
{
return foo(FWD(arg));
}</code></pre>
</td>
<td>
<pre style="background:transparent;border:0px"><code class="language-cpp">foo</code></pre>
</td>
</tr>
</table>
<p>But they are unfortunately not equivalent today, so we have to write the stuff on the left. But the idea we want to express is <em>just</em> to invoke a function by name. Having to explicitly list all of the arguments twice - once in the parameter list, once in the call expression of the lambda body (or even four times in the <em>noexcept-specifier</em> and <em>trailing-return-type</em>) - does not aid the reader in any way.</p>
<p>This is a real problem today. There are many, many higher-order functions that exist in C++ code. They exist in the standard library algorithms, they exist in user-provided libraries. With the adoption of <a href="https://wg21.link/p0896r2" title="The One Ranges Proposal">Ranges</a>, we will get many more - both in terms of algorithms, projections on algorithms, and views. Higher-order functions are ubiquitous, and incredibly useful. Unfortunately, user problems in trying to pass callables to them are just as ubiquitous <sup><a href="https://stackoverflow.com/q/46587694/2069064">[1]</a> <a href="https://stackoverflow.com/q/47984031/2069064">[2]</a> <a href="https://stackoverflow.com/q/24874478/2069064">[3]</a> <a href="https://stackoverflow.com/q/43502837/2069064">[4]</a> <a href="https://stackoverflow.com/q/46146346/2069064">[5]</a> <a href="https://stackoverflow.com/q/44730281/2069064">[6]</a> <a href="https://stackoverflow.com/q/43141181/2069064">[7]</a> ...</sup>. It's important to give users a solution to this problem, that preferably is not reaching for a macro like <code class="language-cpp">OVERLOADS_OF</code> or having to manually write a lambda (possibly inefficiently).</p>
<p>Being able to write just the function name, as opposed to having to list the arguments and the body, is sometimes referred to as <a href="https://en.wikipedia.org/wiki/Tacit_programming" title="Tacit programming - Wikipedia">"<strong>point-free</strong>" programming</a>, a term more commonly used in languages like Haskell. Being able to write point-free in the context of C++ means being able to pass in names and have that <em>just work</em> regardless of what the name happens to refer to. It means that any time <code class="language-cpp">foo(x)</code> works that <code class="language-cpp">algorithm(foo, x)</code> could be made to work also.</p>
<p>Titus Winters in a <a href="https://youtu.be/2UmDvg5xv1U?t=284" title="Modern C++ API Design: From Rvalue-References to Type Design">recent C++Now talk</a> described the overload set as the atom of C++ API design. And yet, we cannot even pass this atom into other atoms with reaching for lambdas, forwarding references, and trailing return types.</p>
<p>We can do better.</p>
<h2 id="history">2. History<a class="self-link" href="#history"></a></h2>
<p>This problem has a long history attached to it, with two different tacks explored.</p>
<p><a href="https://wg21.link/p0119r2" title="Overload sets as function arguments">P0119</a> proposed a syntax-free, "just make it work" approach: synthesize a lambda if, based on a heuristic, it's likely the intended behavior (e.g. if the name nominates an overload set). Unfortunately, this solution fails, as demonstrated in <a href="https://wg21.link/p0382r0" title="Comments on P0119: Overload sets as function arguments">P0382</a>.</p>
<p><a href="https://wg21.link/n3617" title="Lifting overload sets into function objects">N3617</a> (also <a href="https://wg21.link/ewg65" title="N3617 Lifting overload sets into function objects">EWG65</a>) and later <a href="https://wg21.link/p0834r0" title="Lifting overload sets into objects">P0834</a> proposed syntax for the caller to use to explicitly synthesize an overload set:</p>
<pre class="codehilite"><code class="language-cpp">algorithm(getX(), []foo);
std::invoke([]do_something, 42);</code></pre>
<p>This was rejected by EWG in the <a href="http://wiki.edg.com/bin/view/Wg21albuquerque/P0834R0" title="ABQ Wiki Notes, P0834R0 - November 2017">Albuquerque</a>, but it is a syntax that has many benefits. It is point-free and terse enough as to be practically invisible. It would still place the onus on the user to avoid brittleness at each call site, but it is a very manageable burden. That discussion did conclude with this poll:</p>
<blockquote>
<p><em>Are we interested in a core language feature for packing concrete overload sets?</em></p>
<p><table><tr><th>SF</th><th>F</th><th>N</th><th>A</th><th>SA</th></tr><tr><td>3</td><td>4</td><td>14</td><td>0</td><td>1</td></table></p>
</blockquote>
<p><a href="https://wg21.link/p0573r2" title="Abbreviated Lambdas for Fun and Profit">P0573</a> wouldn't have directly solved this problem, but would have at least made writing the direct lambda less burdensome. It was also rejected in <a href="http://wiki.edg.com/bin/view/Wg21albuquerque/P0573R2" title="ABQ Wiki Notes, P0573R2 - November 2017">Albuquerque</a>, and did not even try to solve the point-free problem.</p>
<p>Despite this long history, we believe that this is a problem that needs to be solved. It is unreasonably difficult today to pass a function into another function. The increased emphasis on disallowing users from taking pointers to standard library functions and function templates directly pushes the issue. A significant portion of the discussion of <a href="https://wg21.link/p0798r0" title="Monadic operations for std::optional">P0798</a> in LEWG in <a href="http://wiki.edg.com/bin/view/Wg21rapperswil2018/P0798" title="RAP Wiki Notes, P0798R0 - June 2018">Rapperswil</a> was about the problem of passing overload sets into functions - because the paper would simply introduce more places where users may want to do such a thing. Notably, LEWG took these polls:</p>
<blockquote>
<p><em>Assuming the language gets fixed so we can pass overload sets to callables, we want something like this (either as a general monad syntax or specifically in optional).</em></p>
<p><table><tr><th>SF</th><th>F</th><th>N</th><th>A</th><th>SA</th></tr><tr><td>12</td><td>4</td><td>0</td><td>0</td><td>0</td></table></p>
<p><em>We want something like this, even if the language is not fixed with respect to overload sets.</em></p>
<p><table><tr><th>SF</th><th>F</th><th>N</th><th>A</th><th>SA</th></tr><tr><td>5</td><td>4</td><td>3</td><td>1</td><td>1</td></table></p>
</blockquote>
<p>This is a problem that needs solving, and it has to be solved at the language level.</p>
<h2 id="proposal">3. Proposal<a class="self-link" href="#proposal"></a></h2>
<p>The community tried to solve this problem without adding any syntax, and it tried to solve this problem by adding syntax on the caller's site. We propose a new approach: adding syntax on the function declaration itself. That is, rather than having overload sets as function <em>arguments</em> we instead have overload sets as function <em>parameters</em>.</p>
<p>We propose a new magic library type, <code class="language-cpp">std::overload_set<T></code> (see <a href="#alternative-spellings">alternative spellings</a>) that will deduce an overload set, and we will call this new object an <em>overload set object</em>. The fundamental goal driving the design of <code class="language-cpp">overload_set</code> is that anywhere <code class="language-cpp">foo(a, b, c)</code> works today, <code class="language-cpp">std::overload_set(foo)(a, b, c)</code> should also work and have the same meaning:</p>
<pre class="codehilite"><code class="language-cpp">void foo(int); // #1
void foo(int, int); // #2
template <typename F, typename... Args>
void algorithm(std::overload_set<F> f, Args... args) {
f(args...);
}
foo(1); // calls #1
foo(2, 3); // calls #2
algorithm(foo, 1); // ok: calls #1
algorithm(foo, 2, 3); // ok: calls #2
std::overload_set f = foo; // note: deduction guide magic
f(1); // ok: calls #1
f(2, 3); // ok: calls #2</code></pre>
<p>The difference is that, instead of burdening the caller to annotate each and every function, it's up to the API to do that annotation. There are many more callers than callees, so this seems like it places the burden on the correct party. APIs that use <code class="language-cpp">overload_set</code> would be very friendly for users, and would allow for a point-free style.</p>
<p>For legacy APIs that do not use <code class="language-cpp">overload_set</code> for their callables, <code class="language-cpp">overload_set</code> can be used on the call site as a substitute for the macro. This is admittedly much longer than the <code class="language-cpp">[]</code> proposed in P0834/N3617, but it is at least substantially better than a macro. And legacy APIs can be easily transitioned to take advantage of this feature by simply adding <a href="#standard-library-functions-now-and-future">another overload</a>.</p>
<h3 id="implementation-details">3.1. Implementation details<a class="self-link" href="#implementation-details"></a></h3>
<p>An <code class="language-cpp">overload_set<T></code> contains a <code class="language-cpp">T</code> and has a call operator that forwards to <code class="language-cpp">T</code>'s call operator. Its copy and move constructors and assignment operators are defaulted, its other constructors are unspecified.</p>
<p>A hypothetical implementation might look like:</p>
<pre class="codehilite"><code class="language-cpp">template <typename T>
class overload_set {
T f;
public:
overload_set(/* unspecified */);
overload_set(overload_set const&) = default;
overload_set(overload_set&&) = default;
overload_set& operator=(overload_set const&) = default;
overload_set& operator=(overload_set&&) = default;
~overload_set() = default;
template <typename... Us>
invoke_result_t<F&, Us...> operator()(Us&&... us) &
noexcept(is_nothrow_invocable_v<F&, Us...>);
template <typename... Us>
invoke_result_t<F const&, Us...> operator()(Us&&... us) const&
noexcept(is_nothrow_invocable_v<F const&, Us...>);
template <typename... Us>
invoke_result_t<F, Us...> operator()(Us&&... us) &&
noexcept(is_nothrow_invocable_v<F, Us...>);
template <typename... Us>
invoke_result_t<F const, Us...> operator()(Us&&... us) const&&
noexcept(is_nothrow_invocable_v<F const, Us...>);
};</code></pre>
<p>With appropriate deduction guides. An open question is whether or not an <code class="language-cpp">overload_set<T></code> should be (explicitly or implicitly) convertible to a <code class="language-cpp">T</code>.</p>
<h3 id="constraining-on-overload_set">3.2. Constraining on <code class="language-cpp">overload_set</code><a class="self-link" href="#constraining-on-overload_set"></a></h3>
<p>Since <code class="language-cpp">overload_set<T></code> simply contains a <code class="language-cpp">T</code>, and its call operators are based on <code class="language-cpp">T</code>s, this interacts very well with how template constraints are written:</p>
<pre class="codehilite"><code class="language-cpp">// SFINAE constraint has the desired effect
template <typename F, enable_if_t<is_invocable_v<F&, int>, int> = 0>
void foo(overload_set<F> f) {
f(42);
}
// trailing-return constrained has the desired effect
template <typename F>
auto foo(overload_set<F> f) -> decltype(f(17)) {
return f(17);
}
// concept has the desired effect
template <LvalueInvocable<int> F>
void bar(overload_set<F> f) {
f(63);
}</code></pre>
<h3 id="deduction-rules">3.3. Deduction rules<a class="self-link" href="#deduction-rules"></a></h3>
<p>The annotation <code class="language-cpp">overload_set</code> will trigger new deduction rules based not just on the type of the argument it is being deduced from, but also on its <em>name</em>, and even the token sequence.</p>
<p>There are many cases we're proposing, each will synthesize a slightly different function object. We will go over these proposed deduction rules in detail, and then <a href="#summary-of-deduction-rules">summarize them</a>.</p>
<h4 id="deducing-from-an-object">3.3.1. Deducing from an object<a class="self-link" href="#deducing-from-an-object"></a></h4>
<p>If the argument is an object, whether it is a function object or a pointer (or reference) to function or pointer to member, then <code class="language-cpp">overload_set<T></code> deduces <code class="language-cpp">T</code> as the object's type:</p>
<pre class="codehilite"><code class="language-cpp">auto square = [](int i){ return i * i; };
template <typename T> void deduce(std::overload_set<T> f);
deduce(square); // deduce T as decltype(square)</code></pre>
<p>The function parameter <code class="language-cpp">f</code> will have the same underlying type as <code class="language-cpp">square</code>. There is no synthesis of a new lambda in this scenario, we are just copying the lambda. </p>
<p>An <code class="language-cpp">overload_set</code> can be deduced from an object if that object is callable. It must be either a pointer or reference to function or member function, or have class type with at least one declared <code class="language-cpp">operator()</code> or one declared conversion function which can create a surrogate call function as per <a href="http://eel.is/c++draft/over.call.object" title="[over.call.object]">[over.call.object]</a>. For any other type, <code class="language-cpp">overload_set</code> cannot be deduced:</p>
<pre class="codehilite"><code class="language-cpp">deduce(42); // error
deduce(new int); // error
deduce(&square); // error
deduce("hi"s); // error</code></pre>
<p>We also propose that deducing an <code class="language-cpp">overload_set</code> whose template type parameter is an rvalue reference to <em>cv</em>-unqualified template parameter behaves as a forwarding reference. Since <code class="language-cpp">overload_set<T></code> is simply a <code class="language-cpp">T</code>, <code class="language-cpp">overload_set<T&></code> is likewise simply a <code class="language-cpp">T&</code>. This allows for overload set objects that are actually references:</p>
<pre class="codehilite"><code class="language-cpp">// copy
template <typename T> auto f_copy(overload_set<T> f) { return f; }
// const copy
template <typename T> auto f_const(overload_set<T const> f) { return f; }
// lvalue reference
template <typename T> auto f_lref(overload_set<T&> f) { return f; }
// forwarding reference
template <typename T> auto f_fref(overload_set<T&&> f) { return f; }
struct Counter {
int i;
int operator() { return ++i; }
};
Counter c{0};
c();
assert(c.i == 1);
f_copy(c)();
assert(c.i == 1);
f_const(c)(); // ill-formed, Counter::operator() isn't const
f_lref(c)();
assert(c.i == 2);
f_fref(c)(); // calls f_fref<Counter&>, because forwarding reference
assert(c.i == 3);</code></pre>
<p>This allows the API to avoid copying if it so desires. </p>
<p>This rule gives the appearance of the <code class="language-cpp">&</code> simply being in the wrong place. But there is a difference between <code class="language-cpp">overload_set<T&></code> (an overload set object which is a reference to a callable object) and <code class="language-cpp">overload_set<T>&</code> (a reference to an overload set object).</p>
<h4 id="deducing-from-a-name-of-a-function">3.3.2. Deducing from a name of a function<a class="self-link" href="#deducing-from-a-name-of-a-function"></a></h4>
<p>If the argument is the (qualified or unqualified) name of a function, function template, static member function or static member function template, or an overload set containing any number of either, then <code class="language-cpp">overload_set<T></code> deduces <code class="language-cpp">T</code> as a synthesized lambda in the style of <code class="language-cpp">OVERLOADS_OF</code>:</p>
<pre class="codehilite"><code class="language-cpp">[](auto&& ...args) noexcept(noexcept(name(FWD(args)...)))
-> decltype(name(FWD(args)...)) {
return name(FWD(args)...);
}</code></pre>
<p>Qualified names synthesize a lambda that makes a qualified call. Unqualified names synthesize a lambda that makes an unqualified call. Note that this lambda has no capture - we're just calling functions by name.</p>
<p>This is true even if name lookup finds <em>one single</em> function:</p>
<pre class="codehilite"><code class="language-cpp">int square(int i) {
return i * i;
}
// note that square is not an object here, it's the name of a function.
// the underlying type of f is a lambda, not a function pointer
auto f = std::overload_set(square);</code></pre>
<p>The reason for this is we want to have ADL still work:</p>
<pre class="codehilite"><code class="language-cpp">void g(int);
void h(int);
void h(double);
namespace N {
struct X { };
void g(X);
void h(X);
}
auto over_g = std::overload_set(g);
auto over_h = std::overload_set(h);
over_g(N::X{}); // ok, calls N::g... not an error trying to invoke ::g
over_h(N::X{}); // ok, calls N::h</code></pre>
<p>Note that this is only the case if we deduce by <em>name</em>. If we had instead passed in a pointer to <code class="language-cpp">g</code>, we would be in the object case described in the previous section:</p>
<pre class="codehilite"><code class="language-cpp">auto ptr_g = std::overload_set(&g);
ptr_g(0); // ok
ptr_g(N::X{}); // error, no conversion from N::X to int
auto ptr_h = std::overload_set(&h); // error: unresolved overloaded function</code></pre>
<p>The lookup set is frozen at the time of the construction of the overload set object, in the same way it would be had we done it manually:</p>
<pre class="codehilite"><code class="language-cpp">void foo(int);
auto f1 = std::overload_set(foo);
void foo(double);
auto f2 = std::overload_set(foo);
f1(2.0); // calls foo(int)
f2(2.0); // calls foo(double)</code></pre>
<p>This works with function templates or qualified names:</p>
<pre class="codehilite"><code class="language-cpp">namespace N {
template <typename T> T twice(T);
}
std::invoke(overload_set(N::twice), 1); // calls N::twice<int>
std::invoke(overload_set(N::twice), "hi"s); // calls N::twice<std::string></code></pre>
<p>It is unspecified whether or not multiple overload set objects created for the same name in the same context have the same type.</p>
<p>This works even with function templates where one template parameter is explicitly provided but the rest are deduced:</p>
<pre class="codehilite"><code class="language-cpp">template <typename T, typename U>
T convert_to(U);
// this is okay
auto to_int = overload_set(convert_to<int>);
to_int(1); // ok: calls convert_to<int, int>
to_int(2.0); // ok: calls convert_to<int, double>
// but not this
auto convert = overload_set(convert_to);
convert(1); // error: can't deduce T
convert<int>(1); // error: the 'int' would apply to the argument of convert
// there's no 'passthrough' of template parameters</code></pre>
<p>It is an open question as to whether or not parenthesized unqualified names should disable ADL (and get early diagnosed typos) or not:</p>
<pre class="codehilite"><code class="language-cpp">void foo(int);
namespace N {
struct X { };
void foo(X);
}
auto f = std::overload_set((foo)); // NB: parenthesized
f(N::X{}); // ok or error?</code></pre>
<p>Does that call succeed (ADL finding <code class="language-cpp">N::foo</code>) or does the synthesized function behave as if <code class="language-cpp">(foo)(FWD(args)...)</code>, which would not consider ADL, and hence fail with no matching overload?</p>
<h5 id="deducing-from-a-name-that-cannot-be-found-by-unqualified-lookup">3.3.2.1. Deducing from a name that cannot be found by unqualified lookup<a class="self-link" href="#deducing-from-a-name-that-cannot-be-found-by-unqualified-lookup"></a></h5>
<p>Consider a slight variation from an example from the previous section:</p>
<pre class="codehilite" data-line="7,12,16"><code class="language-cpp">void g(int);
void h(int);
void h(double);
namespace N {
struct X { };
void f(X);
void g(X);
void h(X);
}
auto over_f = std::overload_set(f);
auto over_g = std::overload_set(g);
auto over_h = std::overload_set(h);
over_f(N::X{});
over_g(N::X{});
over_h(N::X{});</code></pre>
<p>Should this work? In the previous section, we introduced a rule based on synthesizing a lambda if name lookup finds a function or function template or overload set... but on line 12 here, name lookup on <code class="language-cpp">f</code> finds nothing. Can we really ignore that?</p>
<p>Perhaps <code class="language-cpp">f</code> was a typo, and the programmer really meant <code class="language-cpp">g</code> and we would be doing them a disservice if we do not diagnose at the point of its use on line 12. </p>
<p>On the other hand, a user trying to pass the name <code class="language-cpp">f</code> into a function would write this code:</p>
<pre class="codehilite"><code class="language-cpp">auto over_f = [](auto e) { return f(e); };
over_f(N::X{});</code></pre>
<p>which would diagnose at the point of call rather than at the point of the declaration of the lambda if there was no such function <code class="language-cpp">f</code>. </p>
<p>The motivation of this paper is very much to allow for the separation of the function from its arguments, and since in the original example <code class="language-cpp">f(N::X{})</code> would work (by finding <code class="language-cpp">N::f</code> via ADL), we firmly believe that <code class="language-cpp">std::overload_set(f)(N::X{})</code> should work as well.</p>