-
Notifications
You must be signed in to change notification settings - Fork 0
/
p0725r0.html
773 lines (716 loc) · 30.5 KB
/
p0725r0.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
<!doctype html public "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
<head>
<title>Remove the requirement for constrained-type-specifiers to be deduced to the same type from the Concepts TS</title>
<style type="text/css">
table#header th,
table#header td
{
text-align: left;
}
table#references th,
table#references td
{
vertical-align: top;
}
blockquote.code
{
background-color: #F1F1F1;
border: 1px solid #D1D1D1;
}
ins, ins * { text-decoration:none; font-weight:bold; background-color:#A0FFA0 }
del, del * { text-decoration:line-through; background-color:#FFA0A0 }
#hidedel:checked ~ * del, #hidedel:checked ~ * del * { display:none; visibility:hidden }
blockquote
{
color: #000000;
background-color: #F1F1F1;
border: 1px solid #D1D1D1;
padding-left: 0.5em;
padding-right: 0.5em;
}
blockquote.stdins
{
text-decoration: underline;
color: #000000;
background-color: #C8FFC8;
border: 1px solid #B3EBB3;
padding: 0.5em;
}
blockquote.stddel
{
text-decoration: line-through;
color: #000000;
background-color: #FFEBFF;
border: 1px solid #ECD7EC;
padding-left: 0.5empadding-right: 0.5em;
}
blockquote.code
{
background-color: #F1F1F1;
border: 1px solid #D1D1D1;
}
</style>
</head>
<body>
<table id="header">
<tr>
<th>Document Number:</th>
<td>P0725R0</td>
</tr>
<tr>
<th>Date:</th>
<td>2017-07-03</td>
</tr>
<tr>
<th>Audience:</th>
<td>Evolution Working Group</td>
</tr>
<tr>
<th>Reply-to:</th>
<td>Tom Honermann <[email protected]></td>
</tr>
</table>
<h1>Remove the requirement for constrained-type-specifiers to be deduced to
the same type from the Concepts TS</h1>
<ul>
<li><a href="#introduction">
Introduction</a></li>
<li><a href="#terminology">
Terminology</a></li>
<li><a href="#motivation">
Motivation</a></li>
<li><a href="#wording">
Wording</a></li>
<li><a href="#acknowledgements">
Acknowledgements</a></li>
<li><a href="#references">
References</a></li>
</ul>
<h1 id="introduction">Introduction</h1>
<p>The requirement that each occurrence of a <em>constrained-type-specifier</em>
appearing in the type of a variable declaration, return type of a function
declaration, type of a parameter in an abbreviated function declaration or
generic lambda expression, or the type of a deduction constraint be deduced
to the same type has been controversial as evidenced by various discussions
within the committee reflectors, positions stated by committee members in
advance of the Toronto 2017 meeting, and the
<a title="P0464R2: Revisiting the meaning of <tt>foo(ConceptName,ConceptName)</tt>"
href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0464r2.html">
P0464R2</a>
<sup><a title="P0464R2: Revisiting the meaning of <tt>foo(ConceptName,ConceptName)</tt>"
href="#ref_p0464r2">
[P0464R2]</a></sup> and
<a title="P0691R0: Integrating Concepts: “Open” items for consideration"
href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0691r0.pdf">
P0691R0</a>
<sup><a title="P0691R0: Integrating Concepts: “Open” items for consideration"
href="#ref_p0691r0">
[P0691R0]</a></sup>
paper submissions. This paper proposes removing the same type deduction
requirement from the Concepts TS with the goal of increasing consensus on
adopting the remaining Concepts TS functionality into the current working
paper.
</p>
<p>Removal of support for the same type deduction requirement means that the
following examples that are currently ill-formed according to the Concepts TS
will now be well-formed.
<blockquote class="code">
<tt><pre>
template<typename> concept bool C = true;
template<typename, typename> class ct {};
ct<C,C> v1 = ct<int,char>{}; <em>// Previously ill-formed; each occurence of <tt>C</tt> is</em>
<em>// not deduced to the same type. Now ok.</em>
ct<C,C> f1() {
return ct<int,char>{}; <em>// Previously ill-formed; each occurence of <tt>C</tt> is</em>
<em>// not deduced to the same type. Now ok.</em>
}
ct<C,C> af1(C) {
return ct<int,char>{};
}
auto v2 = af1(0L); <em>// Previously results in an instantiation error due</em>
<em>// to <tt>C</tt> being deduced to <tt>long</tt> from the function</em>
<em>// argument and <tt>ct<int,char></tt> not being convertible</em>
<em>// to <tt>ct<long,long></tt>. Now ok; the return type is</em>
<em>// deduced to <tt>ct<int,char></tt>.</em>
auto gl1 = [](C,C){};
auto v3 = gl1(0,'c'); <em>// Previously results in an instantiation error due</em>
<em>// to different types being deduced for each occurence</em>
<em>// of <tt>C</tt></em> in the generic lambda expression's parameter</em>
<em>// list. Now ok.</em>
template<typename T> concept bool X =
requires (T t) {
{ t } -> ct<C,C>;
};
static_assert(X<ct<int,char>>); <em>// Previously fails; <tt>ct<int,char></tt> doesn't satisfy</em>
<em>// the deduction constraint. Now ok.</em>
</pre></tt>
</blockquote>
</p>
<p>This change would affect, perhaps siliently, the behavior of existing code.
Consider the following example:
<blockquote class="code">
<tt><pre>
C af2(int i, C) { <em>// Previously, the return type was deduced from the function</em>
return i; <em>// argument. Now, it is deduced from the return statement.</em>
}
auto v3 = af2(0, 0L); <em>// Previously resulted in <tt>v3</tt> having type <tt>long</tt>.</em>
<em>// Now <tt>v3</tt> is deduced to have type <tt>int</tt>.</em>
</pre></tt>
</blockquote>
</p>
<p>Additionally, the following code would become ill-formed due to the return
type no longer being deducible.
<blockquote class="code">
<tt><pre>
C af3(C) { <em>// Previously ok; the return type matches the deduced type</em>
return {}; <em>// for the function argument. Now ill-formed since the</em>
} <em>// return type is not deducible from the return statement.</em>
</pre></tt>
</blockquote>
</p>
<p>This paper does <strong>not</strong> propose changing the requirement that
the same type be deduced when multiple declarators are present
[ <em>Note:</em> gcc 7.1.0 and earlier fail to diagnose differently deduced
types for each declarator when the declared type includes
<em>constrained-type-specifiers</em>. See
<a title="[concepts] ill-formed code with a constrained variable declaration with multiple declarators with different deduced types not rejected"
href="https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81270">
gcc bug 81270</a>
<sup><a title="[concepts] ill-formed code with a constrained variable declaration with multiple declarators with different deduced types not rejected"
href="#ref_gccbug81270">
[GccBug81270]</a></sup> — <em>end note</em> ]:
<blockquote class="code">
<tt><pre>
ct<C,C> v4 = ct<int,char>{}, <em>// Previously ill-formed; different types are deduced</em>
v5 = ct<int,long>{}; <em>// for the types of <tt>v4</tt> and <tt>v5</tt>. Remains ill-formed.</em>
</pre></tt>
</blockquote>
</p>
<h1 id="terminology">Terminology</h1>
<p>Some of these terms have been adopted from
<a title="P0694R0: Function declarations using concepts"
href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0694r0.pdf">
P0694R0</a>
<sup><a title="P0694R0: Function declarations using concepts"
href="#ref_p0694r0">
[P0694R0]</a></sup>.
</p>
<ul>
<li><strong>Consistent resolution</strong><br/>
<em>Consistent resolution</em> describes the current behavior of the
Concepts TS in which repeated use of a <em>constrained-type-specifier</em>
within a declaration requires that the same type be deduced for each
occurrence. That is, given <tt>ct<C,C></tt> from the introduction,
a call to the following invented function template must succeed.
<blockquote class="code">
<tt><pre>
template<C T> void ft(ct<T,T>);
</pre></tt>
</blockquote>
</li>
<li><strong>Independent resolution</strong><br/>
<em>Independent resolution</em> describes the alternate behavior proposed
in this paper in which repeated use of a <em>constrained-type-specifier</em>
within a declaration allows each occurrence to be deduced to the same or
a different type. That is, given <tt>ct<C,C></tt> from the
introduction, a call to the following invented function template must
succeed.
<blockquote class="code">
<tt><pre>
template<C T1, C T2> void ft(ct<T1,T2>);
</pre></tt>
</blockquote>
</li>
<li><strong>Matched resolution</strong><br/>
<em>Matched resolution</em> describes behavior not currently available
(outside a function template declaration) in which a type or portion
thereof can be specified as the type deduced for a
<em>constrained-type-specifier</em> present in some deducible context
within the declaration. The extensions proposed in
<a title="N3878: Extensions to the Concept Introduction Syntax in Concepts Lite"
href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3878.pdf">
N3878</a>
<sup><a title="N3878: Extensions to the Concept Introduction Syntax in Concepts Lite"
href="#ref_n3878">
[N3878]</a></sup> provides such support. Given <tt>ct<C{T},T></tt>, a
call to the following invented function template must succeed.
<blockquote class="code">
<tt><pre>
template<typename T> using identity = T;
template<C T> void ft(ct<T, identity<T>>);
</pre></tt>
</blockquote>
</li>
</ul>
<h1 id="motivation">Motivation</h1>
<p>
<a title="P0464R2: Revisiting the meaning of <tt>foo(ConceptName,ConceptName)</tt>"
href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0464r2.html">
P0464R2</a>
<sup><a title="P0464R2: Revisiting the meaning of <tt>foo(ConceptName,ConceptName)</tt>"
href="#ref_p0464r2">
[P0464R2]</a></sup> provides motivation for removing the same-type deduction
requirement (<em>consistent resolution</em>) for abbreviated functions in
favor of allowing different-type deduction (<em>independent resolution</em>).
That motivation is acknowledged and little further motivation with respect to
abbreviated functions is provided here. The following discusses additional
motivation relative to the types of variable declarations, return types of
non-abbreviated functions, and deduction constraints.
</p>
<p>The requirement for types specified by <em>constrained-type-specifier</em>s
to be deduced to the same type within a declaration
(<em>consistent resolution</em>) was introduced based on an expectation that
such resolution would be frequently desired and that non-abbreviated
declarations could be used when not desired. While certainly true that
<em>consistent resolution</em> is often desired, it is also true that is is
often not desired. Use of non-abbreviated declarations does allow precise
specification, but only for function template declarations; there is currently
only one syntax available for variable declarations, non-template function
declarations, and deduction constraints.
</p>
<p>Consider the following variable declaration copied from the introduction.
The declaration is currently ill-formed because the deduced types for both
occurrences of <tt>C</tt> do not match.
<blockquote class="code">
<tt><pre>
ct<C,C> v1 = ct<int,char>{}; <em>// Currently ill-formed.</em>
</pre></tt>
</blockquote>
There are several solutions available for making this well-formed such that
each of the arguments to <tt>ct</tt> are individually deduced, but still
required to satisfy <tt>C</tt>. For example:
<blockquote class="code">
<tt><pre>
template<C T1, C T2> void ctCC_with_independent_resolution(ct<T1,T2>);
template<typename T> concept bool ctCC =
requires (T t) {
ctCC_with_independent_resolution(t);
};
ctCC v1 = ct<int,char>{}; <em>// Ok; <tt>ctCC</tt> allows independent resolution.</em>
</pre></tt>
</blockquote>
<a title="P0694R0: Function declarations using concepts"
href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0694r0.pdf">
P0694R0</a>
<sup><a title="P0694R0: Function declarations using concepts"
href="#ref_p0694r0">
[P0694R0]</a></sup> suggests introducing additional names for the same concept
to enable <em>independent resolution</em>. For example:
<blockquote class="code">
<tt><pre>
template<typename T> concept bool C2 = C<T>; <em>// A duplicated concept definition.</em>
ct<C,C2> v1 = ct<int,char>{}; <em>// Ok; independent resolution</em>
</pre></tt>
</blockquote>
Neither of these solutions is satisfactory. Of course, should the behavior
be changed to <em>independent resolution</em> as proposed in this paper, then
enabling <em>consistent resolution</em> to preserve the current behavior is
equally unsatisfactory (though necessary only if it is desired to
explicitly reject deduction of different types):
<blockquote class="code">
<tt><pre>
template<C T> void ctCC_with_consistent_resolution(ct<T,T>);
template<typename T> concept bool ctCC =
requires (T t) {
ctCC_with_consistent_resolution(t);
};
ctCC v1 = ct<int,char>{}; <em>// Ill-formed (as intended); <tt>ctCC</tt> requires consistent resolution.</em>
</pre></tt>
</blockquote>
<p>The extensions proposed in
<a title="N3878: Extensions to the Concept Introduction Syntax in Concepts Lite"
href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3878.pdf">
N3878</a>
<sup><a title="N3878: Extensions to the Concept Introduction Syntax in Concepts Lite"
href="#ref_n3878">
[N3878]</a></sup> provide additional flexibility, but do not provide the full
range of expression needed. For example:
<blockquote class="code">
<tt><pre>
ct<C{T},T> v1 = ct<int,char>{}; <em>// Not proposed; syntax from N3878.</em>
<em>// Ill-formed (as intended); <tt>C</tt> is deduced to be <tt>int</tt> for the</em>
<em>// first template argument, the second argument is declared</em>
<em>// to match the deduced type for the first argument,</em>
<em>// and <tt>ct<int,char></tt> is not convertible to <tt>ct<int,int></tt>.</em>
</pre></tt>
</blockquote>
For full genericity, it appears extensions like those proposed in both
<a title="N3878: Extensions to the Concept Introduction Syntax in Concepts Lite"
href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3878.pdf">
N3878</a>
<sup><a title="N3878: Extensions to the Concept Introduction Syntax in Concepts Lite"
href="#ref_n3878">
[N3878]</a></sup> and
<a title="P0694R0: Function declarations using concepts"
href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0694r0.pdf">
P0694R0</a>
<sup><a title="P0694R0: Function declarations using concepts"
href="#ref_p0694r0">
[P0694R0]</a></sup> would be needed to enable expressing:
<ul>
<li>Consistent resolution:
<blockquote class="code">
<tt><pre>
ct<C{T},C{T}> v1 = ...; <em>// Such that both occurrences of <tt>C</tt> require matching deduced types.</em>
</pre></tt>
</blockquote>
</li>
<li>Independent resolution:
<blockquote class="code">
<tt><pre>
ct<C,C> v1 = ...; <em>// Such that each occurrence of <tt>C</tt> is independently deduced.</em>
</pre></tt>
</blockquote>
</li>
<li>Matched resolution (enabling conversions):
<blockquote class="code">
<tt><pre>
ct<C{T},T> v1 = ...; <em>// Such that <tt>C</tt> is deduced from the first template argument,</em>
<em>// but not the second.</em>
</pre></tt>
</blockquote>
</li>
</ul>
</p>
<p>The above examples are illustrated with variable declarations, but the
same concerns apply to <em>constrained-type-specifier</em>s in function return
types and deduction constraints as well. Consider the following example
constraint written to require an expression to have a type requiring
<tt>std::tuple</tt> with a specific arity, but constrained element types.
With the changes proposed in this paper, <em>independent resolution</em> will
allow the element types to be deduced to the same or different types. If
<em>consistent resolution</em> is is desired, then that additional requirement
can be added with the (admittedly unsatisfactory) techniques discussed earlier.
<blockquote class="code">
<tt><pre>
template<typename T> concept bool V =
requires (T t) {
{ t } -> std::tuple<C,C,C>;
};
</pre></tt>
</blockquote>
</p>
<p>Abbreviated functions have the behavior that
<em>constrained-type-specifier</em>s specified within the return type of the
function that match a <em>constrained-type-specifier</em> used in a parameter
type are not deduced from non-discarded return statements from the body of the
function (as is the case when the return type is <tt>auto</tt> or
<tt>decltype(auto)</tt>), but are rather replaced by the deduced type for the
matching parameter(s). This behavior introduces the possibility that a change
to the function's parameter list may alter the meaning of the return type.
For example, if this function:
<blockquote class="code">
<tt><pre>
C af4(auto p1);
</pre></tt>
</blockquote>
is modified to add a parameter <tt>p2</tt> with the
<em>constrained-type-specifier</em> <tt>C</tt>:
<blockquote class="code">
<tt><pre>
C af4(auto p1, C p2);
</pre></tt>
</blockquote>
then the change to the parameter list will result in the return type matching
the deduced type for <tt>C</tt> from the parameter list rather than being
deduced from return statements in the function definition. Such an effect is
subtle and may be made unintentionally. Extensions like those discussed above
would enable making these relationships explicit when desired:
<blockquote class="code">
<tt><pre>
auto af4(auto p1, C{T} p2) -> T; <em>// The return type matches the type deduced</em>
<em>// for parameter <tt>p2</tt>.</em>
</pre></tt>
</blockquote>
</p>
<p>
<a title="P0694R0: Function declarations using concepts"
href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0694r0.pdf">
P0694R0</a>
<sup><a title="P0694R0: Function declarations using concepts"
href="#ref_p0694r0">
[P0694R0]</a></sup> argues that <em>consistent resolution</em> should be the
default for variables declared with equivalent <em>constrained-type-specifier</em>s
within the same scope and provides the following example (where <tt>Number</tt>
names a concept):
<blockquote class="code">
<tt><pre>
Number operator+(Number,Number);
template<typename T> concept bool Number2 = requires Number<T>;
void f()
{
Number x = 1+2; <em>// OK</em>
Number y = 1.0+2.0; <em>// error: different type bound to same concept in a single scope</em>
Number2 y = 1.0+2.0; <em>// OK</em>
}
</pre></tt>
</blockquote>
However, <em>consistent reslution</em> as portrayed in this example seems
unworkable as a default for variable declarations at namespace scope since
the first variable declaration would lock in the deduced type associated with
the <em>concept-type-specifier</em> for the remainder of the translation
unit. An exception could, of course, be made for variables declared at
namespace scope, but such a variance in the rules would be surprising and
potentially problematic for code refactoring. Consider replacing several
namespace scope variables with static local variables.
</p>
<p>The examples above illustrate cases where the author feels <em>consistent
resolution</em> results in rejection of code that should be well-formed.
Further, when the desire for <em>consistent resolution</em> is present, the
author feels such constraints should be explicitly specified separately from
general satisfaction of a concept. Finally, since the need to specify all of
<em>consistent resolution</em>, <em>independent resolution</em>, and
<em>matched resolution</em> requirements exists, the author feels more work
is needed. In the mean-time, relaxing the requirement for <em>consistent
resolution</em> will enable more code to be well-formed without having to
resort to the current unstatisfactory workarounds.
</p>
<h1 id="wording">Wording</h1>
<input type="checkbox" id="hidedel">Hide deleted text</input>
<p>These changes are relative to
<a title="Working Draft, C++ extensions for Concepts"
href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/n4674.pdf">
N4674</a>
<sup><a title="Working Draft, C++ extensions for Concepts"
href="#ref_n4674">
[N4674]</a></sup>. If
<a title="P0696R0: Remove abbreviated functions and template-introduction syntax from the Concepts TS"
href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0696r0.html">
P0696R0</a>
<sup><a title="P0696R0: Remove abbreviated functions and template-introduction syntax from the Concepts TS"
href="#ref_p0696r0">
[P0696R0]</a></sup> is adopted, then additional changes relative to the wording
adoped in that paper will be required.
</p>
<p>Remove the added paragraph 4 inserted in 10.1.7.4 [dcl.spec.auto]:
<blockquote>
<del>Add the following after paragraph 3 to describe when
<em>constrained-type-specifier</em>s in the return type refer to template
parameters.</del>
<blockquote>
<del>A <em>constrained-type-specifier</em> <tt>C1</tt> within the declared
return type of an abbreviated function template declaration does not designate
a placeholder if its introduced <em>constraint-expression</em> (10.1.7.4.2)
is determined to be equivalent, using the rules in 17.6.5.1 for comparing
expressions, to the introduced <em>constraint-expression</em> for a
<em>constrained-type-specifier</em> <tt>C2</tt> in the
<em>parameter-declaration-clause</em> of that function declaration. Instead,
<tt>C1</tt> is replaced by the template parameter invented for <tt>C2</tt>
(11.3.5). [ <em>Example:</em></del>
<blockquote class="code">
<tt><pre><del>
template<typename T> concept bool C = true;
template<typename... T> struct Tuple;
C const& f1(C); <em>// has one template parameter and no deduced return type</em>
Tuple<C...> f2(C); <em>// has one template parameter and a deduced return type</em>
</del></pre></tt>
</blockquote>
<del>In the declaration <tt>f1</tt>, the <em>constraint-expression</em>
introduced by the <em>constrained-type-specifier</em>s in the
<em>parameter-declaration-clause</em> and return type are equivalent<del> </del>;
they would both introduce the expression <tt>C<T></tt>, for some invented
template parameter <tt>T</tt>. In <tt>f2</tt>, the use of <tt>C</tt> in the
return type would introduce the <em>constraint-expression</em>
<tt>(C<T> &l&l ...)</tt>, which is distinct from the
<em>constraint-expression</em> <tt>C<T></tt> introduced by the invented
<em>constrained-parameter</em> (17.1) for the
<em>constrained-type-specifier</em> in the
<em>parameter-declaration-clause</em> according to the rules in 11.3.5.
— <em>end example</em></del>
</blockquote>
</blockquote>
</p>
<p>Renumber the subsequent paragraphs 5-16 in 10.1.7.4 [dcl.spec.auto] to
reflect the removal of paragraph 4 and to align the paragraph numbers with
the C++ standard.
</p>
<p>In 10.1.7.4.1 [dcl.spec.auto.deduct] paragraph 3 (corresponding to paragraph
4 in the C++ standard), modify the last example to indicate that each
<em>constrained-type-specifier</em> corresponds to a different invented
template parameter:
<blockquote>
[…]<br/>
[ <em>Example:</em>
<blockquote class="code">
<tt><pre>
auto cf(int) -> Pair<C, C> { return expr; }
</pre></tt>
</blockquote>
The return type of <tt>cf</tt> is deduced from the parameter <tt>p2</tt> in
the call <tt>f2(expr)</tt> of the following invented function:
<blockquote class="code">
<tt><pre>
<del>template<C T> void f2(Pair<T, T>);</del>
<ins>template<C T1, C T2> void f2(Pair<T1, T2>);</ins>
</pre></tt>
</blockquote>
Both <em>constrained-type-specifier</em>s in the return type of <tt>cf</tt>
correspond to <del>the same</del><ins>different</ins> invented template
parameter<ins>s</ins>.
</blockquote>
</p>
<p>Change the text added as 11.3.5 [dcl.fct] paragraph 19:
<blockquote>
Each template parameter is invented as follows.
<ul>
<li>(19.1) — If the placeholder is designated by the <tt>auto</tt>
<em>type-specifier</em>, then the invented template parameter is a type
<em>template-parameter</em>.
</li>
<li>(19.2) — Otherwise, the placeholder is designated by a
<em>constrained-type-specifier</em>, and the invented parameter is a
<em>constrained-parameter</em> (17.1) whose <em>qualified-concept-name</em>
is that of the <em>constrained-type-specifier</em>.
</li>
<li>(19.3) — If the placeholder appears in the <em>decl-specifier-seq</em>
of a function parameter pack (??), or the <em>type-specifier-seq</em>
of a <em>type-id</em> that is a pack expansion, the invented template
parameter is a template parameter pack.
</ul>
All placeholders designated by <em>constrained-type-specifier</em>s <del>whose
corresponding <em>constrained-parameter</em>s would introduce equivalent
<em>constraint-expression</em>s (17.1), using the rules for comparing
expressions in 17.6.5.1, </del>have <del>the same</del><ins>unique</ins>
invented template parameter<ins>s</ins><br/>
<ins>[ <em>Example:</em>
<blockquote class="code">
<tt><pre>
template<typename T> concept bool C = true;
template<typename, typename> class ct {};
void f1(C a, C b);
void f2(ct<C,C>);
C f3(C c);
</pre></tt>
</blockquote>
The types of <tt>a</tt>, <tt>b</tt>, <tt>c</tt>, and the template arguments
to <tt>ct</tt> each correspond to unique invented template type parameters.
The return type of <tt>f3</tt> is deduced from non-discarded return statements,
if any, in the body of the function (9.4.1).
<em>— end example</em> ]</ins>
<del>[ <em>Example:</em>
<blockquote class="code">
<tt><pre>
namespace N {
template<typename T> concept bool C = true;
}
template<typename T> concept bool C = true;
template<typename T, int> concept bool D = true;
template<typename, int = 0> concept bool E = true;
void abbr(C, D<0>);
</pre></tt>
</blockquote>
The <em>constrained-type-specifier</em>s <tt>C</tt> and <tt>D<0></tt>
correspond to distinct invented template parameters in the declaration of
<tt>abbr</tt>.
<blockquote class="code">
<tt><pre>
void f0(C a, C b);
</pre></tt>
</blockquote>
The types of <tt>a</tt> and <tt>b</tt> are the same invented template type
parameter.
<blockquote class="code">
<tt><pre>
void f1(C& a, C* b);
</pre></tt>
</blockquote>
The type of <tt>a</tt> is a reference to an invented template type parameter
<tt>T</tt>, and the type of <tt>b</tt> is a pointer to <tt>T</tt>.
<blockquote class="code">
<tt><pre>
void f2(N::C a, C b);
void f3(D<0> a, D<1> b);
</pre></tt>
</blockquote>
In both functions, the parameters <tt>a</tt> and <tt>b</tt> have different
invented template type parameters.
<blockquote class="code">
<tt><pre>
void f4(E a, E<> b, E<0> c);
</pre></tt>
</blockquote>
The types of <tt>a</tt>, <tt>b</tt>, and <tt>c</tt> are the same because the
<em>constrained-type-specifier</em>s <tt>E</tt>, <tt>E<></tt>, and
<tt>E<0></tt> all associate the <em>constraint-expression</em>
<tt>E<T, 0></tt>, where <tt>T</tt> is an invented template type
parameter.
<blockquote class="code">
<tt><pre>
void f5(C head, C... tail);
</pre></tt>
</blockquote>
The types of <tt>head</tt> and <tt>tail</tt> are different. Their respective
introduced <em>constraint-expression</em>s are <tt>C<T></tt> and
<tt>(C<U> && ...)</tt>, where <tt>T</tt> is the template
parameter invented for <tt>head</tt> and <tt>U</tt> is the template parameter
invented for <tt>tail</tt> (17.1).
</del>
</blockquote>
</p>
<h1 id="acknowledgements">Acknowledgements</h1>
<p>The author would like to thank Andrew Sutton for his continued dedication to
progressing the adoption of Concepts into the C++ working paper.
</p>
<p>Thanks to Botond Ballo for initial draft review and feedback.
</p>
<h1 id="references">References</h1>
<table id="references">
<tr>
<td id="ref_n3878"><sup>[N3878]</sup></td>
<td>
"Extensions to the Concept Introduction Syntax in Concepts Lite"<br/>
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3878.pdf">
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3878.pdf</a>
</td>
</tr>
<tr>
<td id="ref_n4674"><sup>[N4674]</sup></td>
<td>
"Working Draft, C++ Extensions for concepts"<br/>
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/n4674.pdf">
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/n4674.pdf</a>
</td>
</tr>
<tr>
<td id="ref_p0464r2"><sup>[P0464R2]</sup></td>
<td>
"Revisiting the meaning of <tt>foo(ConceptName,ConceptName)</tt>"<br/>
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0464r2.html">
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0464r2.html</a>
</td>
</tr>
<tr>
<td id="ref_p0691r0"><sup>[P0691R0]</sup></td>
<td>
"Integrating Concepts: “Open” items for consideration"<br/>
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0691r0.pdf">
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0691r0.pdf</a>
</td>
</tr>
<tr>
<td id="ref_p0694r0"><sup>[P0694R0]</sup></td>
<td>
"Function declarations using concepts"<br/>
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0694r0.pdf">
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0694r0.pdf</a>
</td>
</tr>
<tr>
<td id="ref_p0696r0"><sup>[P0696R0]</sup></td>
<td>
"Remove abbreviated functions and template-introduction syntax from the Concepts TS"<br/>
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0696r0.html">
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0696r0.html</a>
</td>
</tr>
<tr>
<td id="ref_gccbug81270"><sup>[GccBug81270]</sup></td>
<td>
"[concepts] ill-formed code with a constrained variable declaration with multiple declarators with different deduced types not rejected"<br/>
<a href="https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81270">
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=81270</a>
</td>
</tr>
</table>
</body>