-
Notifications
You must be signed in to change notification settings - Fork 22
/
p1169r4.html
929 lines (921 loc) · 73.9 KB
/
p1169r4.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
<!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-04-08" />
<title>static operator()</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">static <code class="sourceCode cpp"><span class="kw">operator</span><span class="op">()</span></code></h1>
<table style="border:none;float:right">
<tr>
<td>Document #:</td>
<td>P1169R4</td>
</tr>
<tr>
<td>Date:</td>
<td>2022-04-08</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>
Casey Carter<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="#motivation"><span class="toc-section-number">2</span> Motivation<span></span></a></li>
<li><a href="#proposal"><span class="toc-section-number">3</span> Proposal<span></span></a>
<ul>
<li><a href="#overload-resolution"><span class="toc-section-number">3.1</span> Overload Resolution<span></span></a></li>
<li><a href="#lambdas"><span class="toc-section-number">3.2</span> Lambdas<span></span></a>
<ul>
<li><a href="#static-lambdas-with-capture"><span class="toc-section-number">3.2.1</span> Static lambdas with capture<span></span></a></li>
<li><a href="#can-the-static-ness-of-lambdas-be-implementation-defined"><span class="toc-section-number">3.2.2</span> Can the <code class="sourceCode cpp"><span class="kw">static</span></code>-ness of lambdas be implementation-defined?<span></span></a></li>
</ul></li>
<li><a href="#deduction-guides"><span class="toc-section-number">3.3</span> Deduction Guides<span></span></a></li>
<li><a href="#prior-references"><span class="toc-section-number">3.4</span> Prior References<span></span></a></li>
<li><a href="#implementation-experience"><span class="toc-section-number">3.5</span> Implementation Experience<span></span></a></li>
</ul></li>
<li><a href="#wording"><span class="toc-section-number">4</span> Wording<span></span></a>
<ul>
<li><a href="#language-wording"><span class="toc-section-number">4.1</span> Language Wording<span></span></a></li>
<li><a href="#library-wording"><span class="toc-section-number">4.2</span> Library Wording<span></span></a></li>
<li><a href="#feature-test-macro"><span class="toc-section-number">4.3</span> Feature-test macro<span></span></a></li>
</ul></li>
<li><a href="#bibliography"><span class="toc-section-number">5</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="P1169R3">[<a href="#ref-P1169R3" role="doc-biblioref">P1169R3</a>]</span>, wording.</p>
<p>Since <span class="citation" data-cites="P1169R2">[<a href="#ref-P1169R2" role="doc-biblioref">P1169R2</a>]</span>, added missing feature-test macro and updated wording to include <span class="citation" data-cites="LWG3617">[<a href="#ref-LWG3617" role="doc-biblioref">LWG3617</a>]</span>.</p>
<p><span class="citation" data-cites="P1169R1">[<a href="#ref-P1169R1" role="doc-biblioref">P1169R1</a>]</span> was approved for electronic polling by EWG, but two issues came up that while this paper does not <em>change</em> are still worth commenting on: can <a href="#static-lambdas-with-capture">static lambdas still have capture</a> and can whether or not stateless lambdas be <code class="sourceCode cpp"><span class="kw">static</span></code> be <a href="#can-the-static-ness-of-lambdas-be-implementation-defined">implementation-defined</a>?</p>
<p><span class="citation" data-cites="P1169R0">[<a href="#ref-P1169R0" role="doc-biblioref">P1169R0</a>]</span> was presented to EWGI in San Diego, where there was no consensus to pursue the paper. However, recent discussion has caused renewed interest in this paper so it has been resurfaced. R0 of this paper additionally proposed implicitly changing capture-less lambdas to have static function call operators, which would be an breaking change. That part of this paper has been changed to instead allow for an explicit opt-in to static. Additionally, this language change has been implemented.</p>
<h1 data-number="2" style="border-bottom:1px solid #cccccc" id="motivation"><span class="header-section-number">2</span> Motivation<a href="#motivation" class="self-link"></a></h1>
<p>The standard library has always accepted arbitrary function objects - whether to be unary or binary predicates, or perform arbitrary operations. Function objects with call operator templates in particular have a significant advantage today over using overload sets since you can just pass them into algorithms. This makes, for instance, <code class="sourceCode cpp">std<span class="op">::</span>less<span class="op"><>{}</span></code> very useful.</p>
<p>As part of the Ranges work, more and more function objects are being added to the standard library - the set of Customization Point Objects (CPOs). These objects are Callable, but they don’t, as a rule, have any members. They simply exist to do what Eric Niebler termed the <a href="http://ericniebler.com/2014/10/21/customization-point-design-in-c11-and-beyond/">“Std Swap Two-Step”</a>. Nevertheless, the call operators of all of these types are non-static member functions. Because <em>all</em> call operators have to be non-static member functions.</p>
<p>What this means is that if the call operator happens to not be inlined, an extra register must be used to pass in the <code class="sourceCode cpp"><span class="kw">this</span></code> pointer to the object - even if there is no need for it whatsoever. Here is a <a href="https://godbolt.org/z/ajTZo2">simple example</a>:</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">struct</span> X <span class="op">{</span></span>
<span id="cb1-2"><a href="#cb1-2"></a> <span class="dt">bool</span> <span class="kw">operator</span><span class="op">()(</span><span class="dt">int</span><span class="op">)</span> <span class="kw">const</span>;</span>
<span id="cb1-3"><a href="#cb1-3"></a> <span class="kw">static</span> <span class="dt">bool</span> f<span class="op">(</span><span class="dt">int</span><span class="op">)</span>;</span>
<span id="cb1-4"><a href="#cb1-4"></a><span class="op">}</span>;</span>
<span id="cb1-5"><a href="#cb1-5"></a></span>
<span id="cb1-6"><a href="#cb1-6"></a><span class="kw">inline</span> <span class="kw">constexpr</span> X x;</span>
<span id="cb1-7"><a href="#cb1-7"></a></span>
<span id="cb1-8"><a href="#cb1-8"></a><span class="dt">int</span> count_x<span class="op">(</span>std<span class="op">::</span>vector<span class="op"><</span><span class="dt">int</span><span class="op">></span> <span class="kw">const</span><span class="op">&</span> xs<span class="op">)</span> <span class="op">{</span></span>
<span id="cb1-9"><a href="#cb1-9"></a> <span class="cf">return</span> std<span class="op">::</span>count_if<span class="op">(</span>xs<span class="op">.</span>begin<span class="op">()</span>, xs<span class="op">.</span>end<span class="op">()</span>,</span>
<span id="cb1-10"><a href="#cb1-10"></a><span class="pp">#ifdef STATIC</span></span>
<span id="cb1-11"><a href="#cb1-11"></a> X<span class="op">::</span>f</span>
<span id="cb1-12"><a href="#cb1-12"></a><span class="pp">#else</span></span>
<span id="cb1-13"><a href="#cb1-13"></a> x</span>
<span id="cb1-14"><a href="#cb1-14"></a><span class="pp">#endif</span></span>
<span id="cb1-15"><a href="#cb1-15"></a> <span class="op">)</span>;</span>
<span id="cb1-16"><a href="#cb1-16"></a><span class="op">}</span></span></code></pre></div>
</blockquote>
<p><code class="sourceCode cpp">x</code> is a global function object that has no members that is intended to be passed into various algorithms. But in order to work in algorithms, it needs to have a call operator - which must be non-static. You can see the difference in the generated asm btween using the function object as intended and passing in an equivalent static member function:</p>
<table>
<thead>
<tr class="header">
<th><div style="text-align:center">
<strong>Non-static call operator</strong>
</div></th>
<th><div style="text-align:center">
<strong>Static member function</strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td><div class="sourceCode" id="cb2"><pre class="sourceCode nasm"><code class="sourceCode nasm"><span id="cb2-1"><a href="#cb2-1"></a>count_x(<span class="kw">std</span>::vector<<span class="kw">int</span>, <span class="kw">std</span>::allocator<<span class="kw">int</span>> > const&):</span>
<span id="cb2-2"><a href="#cb2-2"></a> <span class="kw">push</span> r12</span>
<span id="cb2-3"><a href="#cb2-3"></a> <span class="kw">push</span> rbp</span>
<span id="cb2-4"><a href="#cb2-4"></a> <span class="kw">push</span> rbx</span>
<span id="cb2-5"><a href="#cb2-5"></a> <span class="kw">sub</span> rsp, <span class="dv">16</span></span>
<span id="cb2-6"><a href="#cb2-6"></a> <span class="kw">mov</span> r12, <span class="dt">QWORD</span> <span class="dt">PTR</span> [rdi+<span class="dv">8</span>]</span>
<span id="cb2-7"><a href="#cb2-7"></a> <span class="kw">mov</span> rbx, <span class="dt">QWORD</span> <span class="dt">PTR</span> [rdi]</span>
<span id="cb2-8"><a href="#cb2-8"></a> <span class="addu"><span class="kw">mov</span> <span class="dt">BYTE</span> <span class="dt">PTR</span> [rsp+<span class="dv">15</span>], <span class="dv">0</span></span></span>
<span id="cb2-9"><a href="#cb2-9"></a> <span class="kw">cmp</span> r12, rbx</span>
<span id="cb2-10"><a href="#cb2-10"></a> <span class="kw">je</span> .L5</span>
<span id="cb2-11"><a href="#cb2-11"></a> <span class="kw">xor</span> <span class="kw">ebp</span>, <span class="kw">ebp</span></span>
<span id="cb2-12"><a href="#cb2-12"></a><span class="fu">.L4:</span></span>
<span id="cb2-13"><a href="#cb2-13"></a> <span class="kw">mov</span> <span class="kw">esi</span>, <span class="dt">DWORD</span> <span class="dt">PTR</span> [rbx]</span>
<span id="cb2-14"><a href="#cb2-14"></a> <span class="addu"><span class="kw">lea</span> rdi, [rsp+<span class="dv">15</span>]</span></span>
<span id="cb2-15"><a href="#cb2-15"></a> <span class="kw">call</span> X::operator()(<span class="kw">int</span>) const</span>
<span id="cb2-16"><a href="#cb2-16"></a> <span class="kw">cmp</span> <span class="kw">al</span>, <span class="dv">1</span></span>
<span id="cb2-17"><a href="#cb2-17"></a> <span class="kw">sbb</span> rbp, <span class="dv">-1</span></span>
<span id="cb2-18"><a href="#cb2-18"></a> <span class="kw">add</span> rbx, <span class="dv">4</span></span>
<span id="cb2-19"><a href="#cb2-19"></a> <span class="kw">cmp</span> r12, rbx</span>
<span id="cb2-20"><a href="#cb2-20"></a> <span class="kw">jne</span> .L4</span>
<span id="cb2-21"><a href="#cb2-21"></a> <span class="kw">add</span> rsp, <span class="dv">16</span></span>
<span id="cb2-22"><a href="#cb2-22"></a> <span class="kw">mov</span> <span class="kw">eax</span>, <span class="kw">ebp</span></span>
<span id="cb2-23"><a href="#cb2-23"></a> <span class="kw">pop</span> rbx</span>
<span id="cb2-24"><a href="#cb2-24"></a> <span class="kw">pop</span> rbp</span>
<span id="cb2-25"><a href="#cb2-25"></a> <span class="kw">pop</span> r12</span>
<span id="cb2-26"><a href="#cb2-26"></a> <span class="kw">ret</span></span>
<span id="cb2-27"><a href="#cb2-27"></a><span class="fu">.L5:</span></span>
<span id="cb2-28"><a href="#cb2-28"></a> <span class="kw">add</span> rsp, <span class="dv">16</span></span>
<span id="cb2-29"><a href="#cb2-29"></a> <span class="kw">xor</span> <span class="kw">eax</span>, <span class="kw">eax</span></span>
<span id="cb2-30"><a href="#cb2-30"></a> <span class="kw">pop</span> rbx</span>
<span id="cb2-31"><a href="#cb2-31"></a> <span class="kw">pop</span> rbp</span>
<span id="cb2-32"><a href="#cb2-32"></a> <span class="kw">pop</span> r12</span>
<span id="cb2-33"><a href="#cb2-33"></a> <span class="kw">ret</span></span></code></pre></div></td>
<td><div class="sourceCode" id="cb3"><pre class="sourceCode nasm"><code class="sourceCode nasm"><span id="cb3-1"><a href="#cb3-1"></a>count_x(<span class="kw">std</span>::vector<<span class="kw">int</span>, <span class="kw">std</span>::allocator<<span class="kw">int</span>> > const&):</span>
<span id="cb3-2"><a href="#cb3-2"></a> <span class="kw">push</span> r12</span>
<span id="cb3-3"><a href="#cb3-3"></a> <span class="kw">push</span> rbp</span>
<span id="cb3-4"><a href="#cb3-4"></a> <span class="kw">push</span> rbx</span>
<span id="cb3-5"><a href="#cb3-5"></a> <span class="kw">mov</span> r12, <span class="dt">QWORD</span> <span class="dt">PTR</span> [rdi+<span class="dv">8</span>]</span>
<span id="cb3-6"><a href="#cb3-6"></a> <span class="kw">mov</span> rbx, <span class="dt">QWORD</span> <span class="dt">PTR</span> [rdi]</span>
<span id="cb3-7"><a href="#cb3-7"></a> <span class="kw">cmp</span> r12, rbx</span>
<span id="cb3-8"><a href="#cb3-8"></a> <span class="kw">je</span> .L5</span>
<span id="cb3-9"><a href="#cb3-9"></a> <span class="kw">xor</span> <span class="kw">ebp</span>, <span class="kw">ebp</span></span>
<span id="cb3-10"><a href="#cb3-10"></a><span class="fu">.L4:</span></span>
<span id="cb3-11"><a href="#cb3-11"></a> <span class="kw">mov</span> <span class="kw">edi</span>, <span class="dt">DWORD</span> <span class="dt">PTR</span> [rbx]</span>
<span id="cb3-12"><a href="#cb3-12"></a> <span class="kw">call</span> X::f(<span class="kw">int</span>)</span>
<span id="cb3-13"><a href="#cb3-13"></a> <span class="kw">cmp</span> <span class="kw">al</span>, <span class="dv">1</span></span>
<span id="cb3-14"><a href="#cb3-14"></a> <span class="kw">sbb</span> rbp, <span class="dv">-1</span></span>
<span id="cb3-15"><a href="#cb3-15"></a> <span class="kw">add</span> rbx, <span class="dv">4</span></span>
<span id="cb3-16"><a href="#cb3-16"></a> <span class="kw">cmp</span> r12, rbx</span>
<span id="cb3-17"><a href="#cb3-17"></a> <span class="kw">jne</span> .L4</span>
<span id="cb3-18"><a href="#cb3-18"></a> <span class="kw">mov</span> <span class="kw">eax</span>, <span class="kw">ebp</span></span>
<span id="cb3-19"><a href="#cb3-19"></a> <span class="kw">pop</span> rbx</span>
<span id="cb3-20"><a href="#cb3-20"></a> <span class="kw">pop</span> rbp</span>
<span id="cb3-21"><a href="#cb3-21"></a> <span class="kw">pop</span> r12</span>
<span id="cb3-22"><a href="#cb3-22"></a> <span class="kw">ret</span></span>
<span id="cb3-23"><a href="#cb3-23"></a><span class="fu">.L5:</span></span>
<span id="cb3-24"><a href="#cb3-24"></a> <span class="kw">pop</span> rbx</span>
<span id="cb3-25"><a href="#cb3-25"></a> <span class="kw">xor</span> <span class="kw">eax</span>, <span class="kw">eax</span></span>
<span id="cb3-26"><a href="#cb3-26"></a> <span class="kw">pop</span> rbp</span>
<span id="cb3-27"><a href="#cb3-27"></a> <span class="kw">pop</span> r12</span>
<span id="cb3-28"><a href="#cb3-28"></a> <span class="kw">ret</span></span></code></pre></div></td>
</tr>
</tbody>
</table>
<p>Even in this simple example, you can see the extra zeroing out of <code class="sourceCode cpp"><span class="op">[</span>rsp<span class="op">+</span><span class="dv">15</span><span class="op">]</span></code>, the extra <code class="sourceCode cpp">lea</code> to move that zero-ed out area as the object parameter - which we know doesn’t need to be used. This is wasteful, and seems to violate the fundamental philosophy that we don’t pay for what we don’t need.</p>
<p>The typical way to express the idea that we don’t need an object parameter is to declare functions <code class="sourceCode cpp"><span class="kw">static</span></code>. We just don’t have that ability in this case.</p>
<h1 data-number="3" style="border-bottom:1px solid #cccccc" id="proposal"><span class="header-section-number">3</span> Proposal<a href="#proposal" class="self-link"></a></h1>
<p>The proposal is to just allow the ability to make the call operator a static member function, instead of requiring it to be a non-static member function. We have many years of experience with member-less function objects being useful. Let’s remove the unnecessary object parameter overhead. There does not seem to be any value provided by this restriction.</p>
<p>There are other operators that are currently required to be implemented as non-static member functions - all the unary operators, assignment, subscripting, conversion functions, and class member access. We do not believe that being able to declare any of these as static will have as much value, so we are not pursuing those at this time. We’re not aware of any use-case for making any of these other operators static, while the use-case of having stateless function objects is extremely common.</p>
<h2 data-number="3.1" id="overload-resolution"><span class="header-section-number">3.1</span> Overload Resolution<a href="#overload-resolution" class="self-link"></a></h2>
<p>There is one case that needs to be specially considered when it comes to overload resolution, which did not need to be considered until now:</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">struct</span> less <span class="op">{</span></span>
<span id="cb4-2"><a href="#cb4-2"></a> <span class="kw">static</span> <span class="kw">constexpr</span> <span class="kw">auto</span> <span class="kw">operator</span><span class="op">()(</span><span class="dt">int</span> i, <span class="dt">int</span> j<span class="op">)</span> <span class="op">-></span> <span class="dt">bool</span> <span class="op">{</span></span>
<span id="cb4-3"><a href="#cb4-3"></a> <span class="cf">return</span> i <span class="op"><</span> j;</span>
<span id="cb4-4"><a href="#cb4-4"></a> <span class="op">}</span></span>
<span id="cb4-5"><a href="#cb4-5"></a></span>
<span id="cb4-6"><a href="#cb4-6"></a> <span class="kw">using</span> P <span class="op">=</span> <span class="dt">bool</span><span class="op">(*)(</span><span class="dt">int</span>, <span class="dt">int</span><span class="op">)</span>;</span>
<span id="cb4-7"><a href="#cb4-7"></a> <span class="kw">operator</span> P<span class="op">()</span> <span class="kw">const</span> <span class="op">{</span> <span class="cf">return</span> <span class="kw">operator</span><span class="op">()</span>; <span class="op">}</span></span>
<span id="cb4-8"><a href="#cb4-8"></a><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">static_assert</span><span class="op">(</span>less<span class="op">{}(</span><span class="dv">1</span>, <span class="dv">2</span><span class="op">))</span>;</span></code></pre></div>
</blockquote>
<p>If we simply allow <code class="sourceCode cpp"><span class="kw">operator</span><span class="op">()</span></code> to be declared <code class="sourceCode cpp"><span class="kw">static</span></code>, we’d have two candidates here: the function call operator and the surrogate call function. Overload resolution between those candidates would work as considering between:</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">operator</span><span class="op">()(</span><em>contrived-parameter</em>, <span class="dt">int</span>, <span class="dt">int</span><span class="op">)</span>;</span>
<span id="cb5-2"><a href="#cb5-2"></a><em>call-function</em><span class="op">(</span><span class="dt">bool</span><span class="op">(*)(</span><span class="dt">int</span>, <span class="dt">int</span><span class="op">)</span>, <span class="dt">int</span>, <span class="dt">int</span><span class="op">)</span>;</span></code></pre></div>
</blockquote>
<p>And currently this is ambiguous because <span>12.2.4.1 <a href="https://wg21.link/over.match.best.general">[over.match.best.general]</a></span>/1.1 stipulates that the conversion sequence for the contrived implicit object parameter of a static member function is neither better nor worse than <em>any other conversion sequence</em>. This needs to be reined in slightly such that the conversion sequence for the contrived implicit object parameter is neither better nor worse than any <em>standard</em> conversion sequence, but still better than user-defined or ellipsis conversion sequences. Such a change would disambiguate this case in favor of the call operator.</p>
<h2 data-number="3.2" id="lambdas"><span class="header-section-number">3.2</span> Lambdas<a href="#lambdas" class="self-link"></a></h2>
<p>A common source of function objects whose call operators could be static but are not are lambdas without any capture. Had we been able to declare the call operator static when lambdas were originally introduced in the language, we would surely have had a lambda such 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">auto</span> four <span class="op">=</span> <span class="op">[]{</span> <span class="cf">return</span> <span class="dv">4</span>; <span class="op">}</span>;</span></code></pre></div>
</blockquote>
<p>desugar into:</p>
<blockquote>
<div class="sourceCode" id="cb7"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb7-1"><a href="#cb7-1"></a><span class="kw">struct</span> __unique <span class="op">{</span></span>
<span id="cb7-2"><a href="#cb7-2"></a> <span class="kw">static</span> <span class="kw">constexpr</span> <span class="kw">auto</span> <span class="kw">operator</span><span class="op">()()</span> <span class="op">{</span> <span class="cf">return</span> <span class="dv">4</span>; <span class="op">}</span>;</span>
<span id="cb7-3"><a href="#cb7-3"></a></span>
<span id="cb7-4"><a href="#cb7-4"></a> <span class="kw">using</span> P <span class="op">=</span> <span class="dt">int</span><span class="op">()</span>;</span>
<span id="cb7-5"><a href="#cb7-5"></a> <span class="kw">constexpr</span> <span class="kw">operator</span> P<span class="op">*()</span> <span class="op">{</span> <span class="cf">return</span> <span class="kw">operator</span><span class="op">()</span>; <span class="op">}</span></span>
<span id="cb7-6"><a href="#cb7-6"></a><span class="op">}</span>;</span>
<span id="cb7-7"><a href="#cb7-7"></a></span>
<span id="cb7-8"><a href="#cb7-8"></a>__unique four<span class="op">{}</span>;</span></code></pre></div>
</blockquote>
<p>Rather than desugaring to a type that has a non-static call operator along with a conversion function that has to return some other function.</p>
<p>However, we can’t simply change such lambdas because this could break code. There exists code that takes a template parameter of callable type and does <code class="sourceCode cpp"><span class="kw">decltype</span><span class="op">(&</span>F<span class="op">::</span><span class="kw">operator</span><span class="op">())</span></code>, expecting the resulting type to be a pointer to member type (which is the only thing it can be right now). If we change captureless lambdas to have a static call operator implicitly, all such code would break for captureless lambdas. Additionally, this would be a language ABI break. While lambdas shouldn’t show up in your ABI anyway, we can’t with confidence state that such code doesn’t exist nor that such code deserves to be broken.</p>
<p>Instead, we propose that this can be opt-in: a lambda is allowed to be declared <code class="sourceCode cpp"><span class="kw">static</span></code>, which will then cause the call operator (or call operator template) of the lambda to be a static member function rather than a non-static member function:</p>
<blockquote>
<div class="sourceCode" id="cb8"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb8-1"><a href="#cb8-1"></a><span class="kw">auto</span> four <span class="op">=</span> <span class="op">[]()</span> <span class="kw">static</span> <span class="op">{</span> <span class="cf">return</span> <span class="dv">4</span>; <span class="op">}</span>;</span></code></pre></div>
</blockquote>
<p>We then also need to ensure that a lambda cannot be declared <code class="sourceCode cpp"><span class="kw">static</span></code> if it is declared <code class="sourceCode cpp"><span class="kw">mutable</span></code> (an inherently non-static property) or has any capture (as that would be fairly pointless, since you could not access any of that capture).</p>
<h3 data-number="3.2.1" id="static-lambdas-with-capture"><span class="header-section-number">3.2.1</span> Static lambdas with capture<a href="#static-lambdas-with-capture" class="self-link"></a></h3>
<p>Consider the situation where a lambda may need to capture something (for lifetime purposes only) but does not otherwise need to reference it. For instance:</p>
<blockquote>
<div class="sourceCode" id="cb9"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb9-1"><a href="#cb9-1"></a><span class="kw">auto</span> under_lock <span class="op">=</span> <span class="op">[</span>lock<span class="op">=</span>std<span class="op">::</span>unique_lock<span class="op">(</span>mtx<span class="op">)]()</span> <span class="kw">static</span> <span class="op">{</span> <span class="co">/* do something */</span>; <span class="op">}</span>;</span></code></pre></div>
</blockquote>
<p>The body of this lambda does not use the capture <code class="sourceCode cpp">lock</code> in any way, so there isn’t anything that inherently prevents this lambda from having a <code class="sourceCode cpp"><span class="kw">static</span></code> call operator. The rule from R1 of this paper was basically:</p>
<blockquote>
<p>A <code class="sourceCode cpp"><span class="kw">static</span></code> lambda shall have no <em>lambda-capture</em>.</p>
</blockquote>
<p>But could instead be:</p>
<blockquote>
<p>If a lambda is <code class="sourceCode cpp"><span class="kw">static</span></code>, then any <em>id-expression</em> within the body of the lambda that would be an odr-use of a captured entity is ill-formed.</p>
</blockquote>
<p>However, we feel that the value of the teachability of “Just make stateless lambdas <code class="sourceCode cpp"><span class="kw">static</span></code>” outweights the value of supporting holding capturing variables that the body of the lambda does not use. This restriction could be relaxed in the future, if it proves overly onerous (much as we are here relaxing the restriction that call operators be non-static member functions).</p>
<p>This aspect was specifically polled during the telecon, and the outcome was:</p>
<table>
<thead>
<tr class="header">
<th><div style="text-align:center">
<strong>SF</strong>
</div></th>
<th><div style="text-align:center">
<strong>F</strong>
</div></th>
<th><div style="text-align:center">
<strong>N</strong>
</div></th>
<th><div style="text-align:center">
<strong>A</strong>
</div></th>
<th><div style="text-align:center">
<strong>SA</strong>
</div></th>
</tr>
</thead>
<tbody>
<tr class="odd">
<td>0</td>
<td>3</td>
<td>4</td>
<td>5</td>
<td>0</td>
</tr>
</tbody>
</table>
<h3 data-number="3.2.2" id="can-the-static-ness-of-lambdas-be-implementation-defined"><span class="header-section-number">3.2.2</span> Can the <code class="sourceCode cpp"><span class="kw">static</span></code>-ness of lambdas be implementation-defined?<a href="#can-the-static-ness-of-lambdas-be-implementation-defined" class="self-link"></a></h3>
<p>Another question arose during the telecon about whether it is feasible or desirable to make it implementation-defined as to whether or not the call operator of a capture-less lambda is <code class="sourceCode cpp"><span class="kw">static</span></code>.</p>
<p>The advantage of making it implementation-defined is that implementations could, potentially, add a flag that would allow users to treat all of their capture-less lambdas as <code class="sourceCode cpp"><span class="kw">static</span></code> without the burden of adding this extra annotation (had call operators been allowed to be static before C++11, surely capture-less lambdas would have been implicitly <code class="sourceCode cpp"><span class="kw">static</span></code>) while still making this sufficiently opt-in as to avoid ABI-breaking changes.</p>
<p>The disadvantage of making it implementation-defined is that this is a fairly important property of how a lambda behaves. Right now, the observable properties of a lambda are specified and portable. The implementation freedom areas are typically not observable to the programmer. The static-ness of the operator is observable, so making that implementation-defined or unspecified seems antithetical to the design of lambdas. The rationale for doing something like this (i.e. avoiding a sea of seemingly-pointless <code class="sourceCode cpp"><span class="kw">static</span></code> annotations when the compiler should be able to Just Do It), but it seems rather weird that a property like that wouldn’t be portable.</p>
<h2 data-number="3.3" id="deduction-guides"><span class="header-section-number">3.3</span> Deduction Guides<a href="#deduction-guides" class="self-link"></a></h2>
<p>Consider the following, assuming a version of <code class="sourceCode cpp">less</code> that uses a static call operator:</p>
<blockquote>
<div class="sourceCode" id="cb10"><pre class="sourceCode cpp"><code class="sourceCode cpp"><span id="cb10-1"><a href="#cb10-1"></a><span class="kw">template</span> <span class="op"><</span><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> less <span class="op">{</span></span>
<span id="cb10-3"><a href="#cb10-3"></a> <span class="kw">static</span> <span class="kw">constexpr</span> <span class="kw">auto</span> <span class="kw">operator</span><span class="op">()(</span>T <span class="kw">const</span><span class="op">&</span> x, T <span class="kw">const</span><span class="op">&</span> y<span class="op">)</span> <span class="op">-></span> <span class="dt">bool</span> <span class="op">{</span></span>
<span id="cb10-4"><a href="#cb10-4"></a> <span class="cf">return</span> x <span class="op"><</span> y;</span>
<span id="cb10-5"><a href="#cb10-5"></a> <span class="op">}</span>;</span>
<span id="cb10-6"><a href="#cb10-6"></a><span class="op">}</span>;</span>
<span id="cb10-7"><a href="#cb10-7"></a></span>
<span id="cb10-8"><a href="#cb10-8"></a>std<span class="op">::</span>function f <span class="op">=</span> less<span class="op"><</span><span class="dt">int</span><span class="op">>{}</span>;</span></code></pre></div>
</blockquote>
<p>This will not compile with this change, because <code class="sourceCode cpp">std<span class="op">::</span>function</code>’s deduction guides only work with either function pointers (which does not apply) or class types whose call operator is a non-static member function. These will need to be extended to support call operators with function type (as they would for <span class="citation" data-cites="P0847R6">[<a href="#ref-P0847R6" role="doc-biblioref">P0847R6</a>]</span> anyway).</p>
<h2 data-number="3.4" id="prior-references"><span class="header-section-number">3.4</span> Prior References<a href="#prior-references" class="self-link"></a></h2>
<p>This idea was previously referenced in <span class="citation" data-cites="EWG88">[<a href="#ref-EWG88" role="doc-biblioref">EWG88</a>]</span>, which reads:</p>
<div class="quote">
<p>In c++std-core-14770, Dos Reis suggests that <code class="sourceCode cpp"><span class="kw">operator</span><span class="op">[]</span></code> and <code class="sourceCode cpp"><span class="kw">operator</span><span class="op">()</span></code> should both be allowed to be static. In addition to that, he suggests that both should allow multiple parameters. It’s well known that there’s a possibility that this breaks existing code (<code class="sourceCode cpp">foo<span class="op">[</span><span class="dv">1</span>,<span class="dv">2</span><span class="op">]</span></code> is valid, the thing in brackets is a comma-expression) but there are possibilities to fix such cases (by requiring parens if a comma-expression is desired). EWG should discuss whether such unification is to be strived for.</p>
<p>Discussed in Rapperswil 2014. EWG points out that there are more issues to consider here, in terms of other operators, motivations, connections with captureless lambdas, who knows what else, so an analysis paper is requested.</p>
</div>
<p>There is a separate paper proposing multi-argument subscripting <span class="citation" data-cites="P2128R3">[<a href="#ref-P2128R3" role="doc-biblioref">P2128R3</a>]</span> already, with preexisting code such as <code class="sourceCode cpp">foo<span class="op">[</span><span class="dv">1</span>, <span class="dv">2</span><span class="op">]</span></code> already having been deprecated.</p>
<h2 data-number="3.5" id="implementation-experience"><span class="header-section-number">3.5</span> Implementation Experience<a href="#implementation-experience" class="self-link"></a></h2>
<p>The language changes have been implemented in EDG.</p>
<h1 data-number="4" style="border-bottom:1px solid #cccccc" id="wording"><span class="header-section-number">4</span> Wording<a href="#wording" class="self-link"></a></h1>
<h2 data-number="4.1" id="language-wording"><span class="header-section-number">4.1</span> Language Wording<a href="#language-wording" class="self-link"></a></h2>
<p>Add <code class="sourceCode cpp"><span class="kw">static</span></code> to the grammar of <span>7.5.5.1 <a href="https://wg21.link/expr.prim.lambda.general">[expr.prim.lambda.general]</a></span>:</p>
<blockquote>
<div>
<div class="sourceCode" id="cb11"><pre class="sourceCode diff"><code class="sourceCode diff"><span id="cb11-1"><a href="#cb11-1"></a> <em>lambda-specifier</em>:</span>
<span id="cb11-2"><a href="#cb11-2"></a> consteval</span>
<span id="cb11-3"><a href="#cb11-3"></a> constexpr</span>
<span id="cb11-4"><a href="#cb11-4"></a> mutable</span>
<span id="cb11-5"><a href="#cb11-5"></a><span class="va">+ static</span></span></code></pre></div>
</div>
</blockquote>
<p>Change <span>7.5.5.1 <a href="https://wg21.link/expr.prim.lambda.general">[expr.prim.lambda.general]</a></span>/4:</p>
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_1" id="pnum_1">4</a></span> A <em>lambda-specifier-seq</em> shall contain at most one of each <em>lambda-specifier</em> and shall not contain both <code class="sourceCode cpp"><span class="kw">constexpr</span></code> and <code class="sourceCode cpp"><span class="kw">consteval</span></code>. If the <em>lambda-declarator</em> contains an explicit object parameter ([dcl.fct]), then no <em>lambda-specifier</em> in the <em>lambda-specifier-seq</em> shall be <code class="sourceCode cpp"><span class="kw">mutable</span></code> <span class="addu">or <code class="sourceCode cpp"><span class="kw">static</span></code></span>. <span class="addu">The <em>lambda-specifier-seq</em> shall not contain both <code class="sourceCode cpp"><span class="kw">mutable</span></code> and <code class="sourceCode cpp"><span class="kw">static</span></code>. If the <em>lambda-specifier-seq</em> contains <code class="sourceCode cpp"><span class="kw">static</span></code>, there shall be no <em>lambda-capture</em></span>.</p>
</blockquote>
<p>Change <span>7.5.5.2 <a href="https://wg21.link/expr.prim.lambda.closure">[expr.prim.lambda.closure]</a></span>/5:</p>
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_2" id="pnum_2">5</a></span> The function call operator or operator template is <span class="addu">a static member function or static member function template ([class.static.mfct]) if the <em>lambda-expression</em>’s <em>parameter-declaration-clause</em> is followed by <code class="sourceCode cpp"><span class="kw">static</span></code>. Otherwise, it is a non-static member function or member function template ([class.mfct.non-static]) that is</span> declared <code class="sourceCode cpp"><span class="kw">const</span></code> ([class.mfct.non.static]) if and only if the <em>lambda-expression</em>’s <em>parameter-declaration-clause</em> is not followed by <code class="sourceCode cpp"><span class="kw">mutable</span></code> and the <em>lambda-declarator</em> does not contain an explicit object parameter. It is neither virtual nor declared <code class="sourceCode cpp"><span class="kw">volatile</span></code>. Any <em>noexcept-specifier</em> specified on a <em>lambda-expression</em> applies to the corresponding function call operator or operator template. An <em>attribute-specifier-seq</em> in a <em>lambda-declarator</em> appertains to the type of the corresponding function call operator or operator template. The function call operator or any given operator template specialization is a <code class="sourceCode cpp"><span class="kw">constexpr</span></code> function if either the corresponding <em>lambda-expression</em>’s <em>parameter-declaration-clause</em> is followed by <code class="sourceCode cpp"><span class="kw">constexpr</span></code>, or it satisfies the requirements for a <code class="sourceCode cpp"><span class="kw">constexpr</span></code> function.</p>
</blockquote>
<p>Add a note to <span>7.5.5.2 <a href="https://wg21.link/expr.prim.lambda.closure">[expr.prim.lambda.closure]</a></span>/8 and /11 indicating that we could just return the call operator. The wording as-is specifies the behavior of the return here, and returning the call operator already would be allowed, so no wording change is necessary. But the note would be helpful:</p>
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_3" id="pnum_3">8</a></span> The closure type for a non-generic <em>lambda-expression</em> with no <em>lambda-capture</em> whose constraints (if any) are satisfied has a conversion function to pointer to function with C++ language linkage having the same parameter and return types as the closure type’s function call operator. The conversion is to “pointer to <code class="sourceCode cpp"><span class="kw">noexcept</span></code> function” if the function call operator has a non-throwing exception specification. <span class="addu">If the function call operator is a static member function, then the value returned by this conversion function is the address of the function call operator. Otherwise, the</span> <span class="rm" style="color: #bf0303"><del>The</del></span> value returned by this conversion function is the address of a function <code class="sourceCode cpp">F</code> that, when invoked, has the same effect as invoking the closure type’s function call operator on a default-constructed instance of the closure type. <code class="sourceCode cpp">F</code> is a constexpr function if the function call operator is a constexpr function and is an immediate function if the function call operator is an immediate function.</p>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_4" id="pnum_4">11</a></span> <span class="addu">If the function call operator template is a static member function template, then the value returned by any given specialization of this conversion function template is the address of the corresponding function call operator template specialization. Otherwise, the</span> <span class="rm" style="color: #bf0303"><del>The</del></span> value returned by any given specialization of this conversion function template is the address of a function <code class="sourceCode cpp">F</code> that, when invoked, has the same effect as invoking the generic lambda’s corresponding function call operator template specialization on a default-constructed instance of the closure type. F is a constexpr function if the corresponding specialization is a constexpr function and F is an immediate function if the function call operator template specialization is an immediate function.</p>
</blockquote>
<p>Change <span>12.2.4.1 <a href="https://wg21.link/over.match.best.general">[over.match.best.general]</a></span>/1 to drop the static member exception and remove the bullets and the footnote:</p>
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_5" id="pnum_5">1</a></span> Define ICS<sup>i</sup>(<code class="sourceCode cpp">F</code>) as <span class="rm" style="color: #bf0303"><del>follows:</del></span></p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_6" id="pnum_6">(1.1)</a></span> <span class="rm" style="color: #bf0303"><del>If <span><code class="sourceCode default">F</code></span> is a static member function, ICS<sup>1</sup>(<span><code class="sourceCode default">F</code></span>) is defined such that ICS<sup>1</sup>(<span><code class="sourceCode default">F</code></span>) is neither better nor worse than ICS<sup>1</sup>(<span><code class="sourceCode default">G</code></span>) for any function <span><code class="sourceCode default">G</code></span>, and, symmetrically, ICS<sup>1</sup>(<span><code class="sourceCode default">G</code></span>) is neither better nor worse than ICS<sup>1</sup>(<span><code class="sourceCode default">F</code></span>);<sup>117</sup> otherwise,</del></span></li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_7" id="pnum_7">(1.2)</a></span> <span class="rm" style="color: #bf0303"><del>let ICS<sup>i</sup>(<span><code class="sourceCode default">F</code></span>) denote</del></span> the implicit conversion sequence that converts the i<sup>th</sup> argument in the list to the type of the i<sup>th</sup> parameter of viable function <code class="sourceCode cpp">F</code>. [over.best.ics] defines the implicit conversion sequences and [over.ics.rank] defines what it means for one implicit conversion sequence to be a better conversion sequence or worse conversion sequence than another.</li>
</ul>
</blockquote>
<p>Add to <span>12.2.4.2.1 <a href="https://wg21.link/over.best.ics.general">[over.best.ics.general]</a></span> a way to compare this static member function case:</p>
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_8" id="pnum_8">*</a></span> <span class="addu">When the parameter is the implicit object parameter of a static member function, the implicit conversion sequence is a standard conversion sequence that is neither better nor worse than any other standard conversion sequence.</span></p>
</blockquote>
<p>Change <span>12.4 <a href="https://wg21.link/over.oper">[over.oper]</a></span> paragraph 6 and introduce bullets to clarify the parsing. <code class="sourceCode cpp"><span class="kw">static</span> <span class="dt">void</span> <span class="kw">operator</span><span class="op">()()</span> <span class="op">{</span> <span class="op">}</span></code> is a valid function call operator that has no parameters with this proposal, so needs to be clear that the “has at least one parameter” part refers to the non-member function part of the clause.</p>
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_9" id="pnum_9">6</a></span> An operator function shall either</p>
<ul>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_10" id="pnum_10">(6.1)</a></span> be a <span class="rm" style="color: #bf0303"><del>non-static</del></span> member function or</li>
<li><span class="marginalizedparent"><a class="marginalized" href="#pnum_11" id="pnum_11">(6.2)</a></span> be a non-member function that has at least one parameter whose type is a class, a reference to a class, an enumeration, or a reference to an enumeration.</li>
</ul>
<p>It is not possible to change the precedence, grouping, or number of operands of operators. The meaning of the operators <code class="sourceCode cpp"><span class="op">=</span></code>, (unary) <code class="sourceCode cpp"><span class="op">&</span></code>, and <code class="sourceCode cpp">,</code> (comma), predefined for each type, can be changed for specific class and enumeration types by defining operator functions that implement these operators. Operator functions are inherited in the same manner as other base class functions.</p>
</blockquote>
<p>Change <span>12.4.4 <a href="https://wg21.link/over.call">[over.call]</a></span> paragraph 1:</p>
<blockquote>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_12" id="pnum_12">1</a></span> A <em>function call operator function</em> is a function named <code class="sourceCode cpp"><span class="kw">operator</span><span class="op">()</span></code> that is a <span class="rm" style="color: #bf0303"><del>non-static</del></span> member function with an arbitrary number of parameters.</p>
</blockquote>
<h2 data-number="4.2" id="library-wording"><span class="header-section-number">4.2</span> Library Wording<a href="#library-wording" class="self-link"></a></h2>
<p>Change the deduction guide for <code class="sourceCode cpp">function</code> in <span>20.14.17.3.2 <a href="https://wg21.link/func.wrap.func.con">[func.wrap.func.con]</a></span>/16-17. <span class="ednote" style="color: #0000ff">[ Editor's note: This assumes the wording change in <span class="citation" data-cites="LWG3617">[<a href="#ref-LWG3617" role="doc-biblioref">LWG3617</a>]</span>. This relies on the fact that <code class="sourceCode default">f.operator()</code> would be valid for a static member function, but not an explicit object member function - which like other non-static member functions you can’t just write <code class="sourceCode default">x.f</code> you can only write <code class="sourceCode default">x.f(args...)</code>. ]</span>:</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">class</span> F<span class="op">></span> function<span class="op">(</span>F<span class="op">)</span> <span class="op">-></span> function<span class="op"><</span><em>see below</em><span class="op">></span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_13" id="pnum_13">15</a></span> <em>Constraints</em>: <code class="sourceCode cpp"><span class="op">&</span>F<span class="op">::</span><span class="kw">operator</span><span class="op">()</span></code> is well-formed when treated as an unevaluated operand and <span class="addu">either</span></p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized" href="#pnum_14" id="pnum_14">(15.1)</a></span> <span class="addu"><code class="sourceCode cpp">F<span class="op">::</span><span class="kw">operator</span><span class="op">()</span></code> is a non-static member function and</span> <code class="sourceCode cpp"><span class="kw">decltype</span><span class="op">(</span><span class="op">&</span>F<span class="op">::</span><span class="kw">operator</span><span class="op">())</span></code> is either of the form <code class="sourceCode cpp">R<span class="op">(</span>G<span class="op">::</span><span class="op">*)(</span>A<span class="op">...)</span> cv <span class="op">&</span><sub>opt</sub> noexcept<sub>opt</sub></code> or of the form <code class="sourceCode cpp">R<span class="op">(*)(</span>G <em>cv</em> <em>ref</em><sub>opt</sub>, A<span class="op">...)</span> noexcept<sub>opt</sub></code> for a type <code class="sourceCode cpp">G</code> <span class="addu">, or</span></p></li>
<li><p><span class="marginalizedparent"><a class="marginalized" href="#pnum_15" id="pnum_15">(15.2)</a></span> <span class="addu"><code class="sourceCode cpp">F<span class="op">::</span><span class="kw">operator</span><span class="op">()</span></code> is a static member function and <code class="sourceCode cpp"><span class="kw">decltype</span><span class="op">(</span><span class="op">&</span>F<span class="op">::</span><span class="kw">operator</span><span class="op">())</span></code> is of the form <code class="sourceCode cpp">R<span class="op">(*)(</span>A<span class="op">...)</span> noexcept<sub>opt</sub></code>.</span></p></li>
</ul>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_16" id="pnum_16">16</a></span> <em>Remarks</em>: The deduced type is <code class="sourceCode cpp">function<span class="op"><</span>R<span class="op">(</span>A<span class="op">...)></span></code>.</p>
</blockquote>
<p>Change the deduction guide for <code class="sourceCode cpp">packaged_task</code> in <span>32.9.10.2 <a href="https://wg21.link/futures.task.members">[futures.task.members]</a></span>/7-8 in the same way:</p>
<blockquote>
<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">class</span> F<span class="op">></span> packaged_task<span class="op">(</span>F<span class="op">)</span> <span class="op">-></span> packaged_task<span class="op"><</span><em>see below</em><span class="op">></span>;</span></code></pre></div>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_17" id="pnum_17">7</a></span> <em>Constraints</em>: <code class="sourceCode cpp"><span class="op">&</span>F<span class="op">::</span><span class="kw">operator</span><span class="op">()</span></code> is well-formed when treated as an unevaluated operand and <span class="addu">either</span></p>
<ul>
<li><p><span class="marginalizedparent"><a class="marginalized" href="#pnum_18" id="pnum_18">(7.1)</a></span> <span class="addu"><code class="sourceCode cpp">F<span class="op">::</span><span class="kw">operator</span><span class="op">()</span></code> is a non-static member function and</span> <code class="sourceCode cpp"><span class="kw">decltype</span><span class="op">(</span><span class="op">&</span>F<span class="op">::</span><span class="kw">operator</span><span class="op">())</span></code> is either of the form <code class="sourceCode cpp">R<span class="op">(</span>G<span class="op">::</span><span class="op">*)(</span>A<span class="op">...)</span> cv <span class="op">&</span><sub>opt</sub> noexcept<sub>opt</sub></code> or of the form <code class="sourceCode cpp">R<span class="op">(*)(</span>G <em>cv</em> <em>ref</em><sub>opt</sub>, A<span class="op">...)</span> noexcept<sub>opt</sub></code> for a type <code class="sourceCode cpp">G</code> <span class="addu">, or</span></p></li>
<li><p><span class="marginalizedparent"><a class="marginalized" href="#pnum_19" id="pnum_19">(7.2)</a></span> <span class="addu"><code class="sourceCode cpp">F<span class="op">::</span><span class="kw">operator</span><span class="op">()</span></code> is a static member function and <code class="sourceCode cpp"><span class="kw">decltype</span><span class="op">(</span><span class="op">&</span>F<span class="op">::</span><span class="kw">operator</span><span class="op">())</span></code> is of the form <code class="sourceCode cpp">R<span class="op">(*)(</span>A<span class="op">...)</span> noexcept<sub>opt</sub></code>.</span></p></li>
</ul>
<p><span class="marginalizedparent"><a class="marginalized" href="#pnum_20" id="pnum_20">8</a></span> <em>Remarks</em>: The deduced type is <code class="sourceCode cpp">packaged_task<span class="op"><</span>R<span class="op">(</span>A<span class="op">...)></span></code>.</p>
</blockquote>
<h2 data-number="4.3" id="feature-test-macro"><span class="header-section-number">4.3</span> Feature-test macro<a href="#feature-test-macro" class="self-link"></a></h2>
<p>Add to <span>15.11 <a href="https://wg21.link/cpp.predefined">[cpp.predefined]</a></span>/table 19:</p>
<blockquote>
<p><span class="addu"><code class="sourceCode cpp">__cpp_static_call_operator</code></span></p>
</blockquote>
<p>with the appropriate value. This allows define function objects or lambdas to have conditionally static call operators when possible.</p>
<h1 data-number="5" style="border-bottom:1px solid #cccccc" id="bibliography"><span class="header-section-number">5</span> References<a href="#bibliography" class="self-link"></a></h1>
<div id="refs" class="references hanging-indent" role="doc-bibliography">
<div id="ref-EWG88">
<p>[EWG88] Gabriel Dos Reis. [tiny] Uniform handling of operator[] and operator(). <br />
<a href="https://wg21.link/ewg88">https://wg21.link/ewg88</a></p>
</div>
<div id="ref-LWG3617">
<p>[LWG3617] Barry Revzin. 2021. <code class="sourceCode cpp">function</code>/<code class="sourceCode cpp">packaged_task</code> deduction guides and deducing <code class="sourceCode cpp"><span class="kw">this</span></code>. <br />
<a href="https://cplusplus.github.io/LWG/issue3617">https://cplusplus.github.io/LWG/issue3617</a></p>
</div>
<div id="ref-P0847R6">
<p>[P0847R6] Barry Revzin, Gašper Ažman, Sy Brand, Ben Deane. 2021-01-15. Deducing this. <br />
<a href="https://wg21.link/p0847r6">https://wg21.link/p0847r6</a></p>
</div>
<div id="ref-P1169R0">
<p>[P1169R0] Barry Revzin, Casey Carter. 2018-10-07. static operator(). <br />
<a href="https://wg21.link/p1169r0">https://wg21.link/p1169r0</a></p>
</div>
<div id="ref-P1169R1">
<p>[P1169R1] Barry Revzin, Casey Carter. 2021-04-06. static operator(). <br />
<a href="https://wg21.link/p1169r1">https://wg21.link/p1169r1</a></p>
</div>
<div id="ref-P1169R2">
<p>[P1169R2] Barry Revzin, Casey Carter. 2021-08-14. static operator(). <br />
<a href="https://wg21.link/p1169r2">https://wg21.link/p1169r2</a></p>
</div>
<div id="ref-P1169R3">
<p>[P1169R3] Barry Revzin, Casey Carter. 2021-10-14. static operator(). <br />
<a href="https://wg21.link/p1169r3">https://wg21.link/p1169r3</a></p>
</div>
<div id="ref-P2128R3">
<p>[P2128R3] Corentin Jabot, Isabella Muerte, Daisy Hollman, Christian Trott, Mark Hoemmen. 2021-02-15. Multidimensional subscript operator. <br />
<a href="https://wg21.link/p2128r3">https://wg21.link/p2128r3</a></p>
</div>
</div>
</div>
</div>
</body>
</html>