-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathD0433R2.html
1085 lines (963 loc) · 64.9 KB
/
D0433R2.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html><head>
<meta http-equiv="content-type" content="text/html; charset=windows-1252">
<style type="text/css">
.comment { color: #999999; font-style: italic; }
.pre { color: #000099; }
.string { color: #009900; }
.char { color: #009900; }
.float { color: #996600; }
.int { color: #999900; }
.bool { color: #000000; font-weight: bold; }
.type { color: #FF6633; }
.flow { color: #FF0000; }
.keyword { color: #990000; }
.operator { color: #663300; font-weight: bold; }
.operator { color: #663300; font-weight: bold; }
pre.code {
border: 2px solid #666;
background-color: #F4F4F4;
padding-left: 10px;
padding-top: 0px;
}
code {
border: 2px solid #d0d0d0;
background-color: LightYellow;
padding: 2px;
padding-left: 10px;
display:table;
white-space:pre;
margin:2px;
margin-bottom:10px;
}
dt {
font-weight: bold;
}
.ins {
background-color:#A0FFA0;
}
.del {
background-color:#FFA0A0;
text-decoration:line-through
}
.TODO {
background-color: LightYellow;
color: red;
}
</style>
<title>Toward a resolution of US7 and US14: Integrating template
deduction for class templates into the standard library</title>
</head>
<body>
<p>Document number: P0433R2 <br>
Date: 2017-03-03<br>
Reply-To:<br>
Mike Spertus, Symantec (<a href="mailto:[email protected]">[email protected]</a>)<br>
Walter E. Brown (<a href="mailto:[email protected]"> [email protected]</a>)<br>
Stephan T. Lavavej (<a href="mailto:[email protected]">[email protected]</a>)<br>
Audience: {Library Evolution, Library} Working Group
</p>
<h1>Toward a resolution of US7 and US14: Integrating template
deduction for class templates into the standard library</h1>
<h2>Introduction</h2>
<p>
National body comments US7 and US14 request analysis of the standard library
to determine what changes might be desirable
in light of the C++17 adoption of <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0091r3.html">P0091R3</a>
(Template argument deduction for class templates (rev. 6)).
In this paper, we perform such an analysis and recommend wording changes
for the standard library clauses.
</p>
<a name="Background"></a><h1>Background</h1>
General background is provided in <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0433r0.html">P0433R0</a>.
We list here new items not reflected in that paper.
<ul>
<li>A sample implementation is available at <a href="https://github.com/mspertus/p0433">https://github.com/mspertus/p0433</a>. The primary impressions from implementation experience are that classes focused on a particular “application domain”
generally work just as one would hope without any changes, which we believe bodes well for C++ programmers developing
applications. E.g.,
<code>string needle = "foo";
auto bms = boyer_moore_searcher(needle.begin(), needle.end());
gamma_distribution gdf{2.5f, .7f};
</code> while heavily-metaprogrammed STL classes (e.g., <tt>vector</tt>) generally require some explicit deduction guides but
that generally proved straightforward. Adapting the entire standard library took about 40 hours, most of which was
spent on writing test cases.</li>
<li>P0091R4 discusses some possible language extensions. Our recommendations in this paper for integrating template
deduction for class templates are not affected in any way
by the adoption or non-adoption of the extensions in that paper. However, it should be noted that these language extensions
were motivated by experience with the standard library. See the next bullet as well as the discussion of <tt>valarray</tt>
below for more information.</li>
<li>As has been noted multiple times on the reflector, scenarios like the following can arise with standard library types
that act as containers for values (e.g., <tt>optional</tt>):
<code>optional o(3); <span class="comment">// Deduces optional<int></span>
optional o2 = o; <span class="comment">// Deduces optional<int></span></code></li>
However, note that writers of template libraries may have to continue to specify some
object constructions in the traditional fashion as illustrated here:
<code>template<typename T> void foo(T t)
{
optional o = t; <span class="comment">// T=optional<int> => o is optional<int>, which may not be desired in generic code</span>
optional<T> o2 = t; <span class="comment">// o2 is optional<optional<int>></span>
}</code>
We feel this is the right tradeoff as application programmers consuming template libraries get full benefit
of deduction and template library writers are not worse off than in C++14. P0091R4 suggests a language
extension to extend deduction to the example above. However, note that this does not impact the present proposal.</ul>
<h1>Wording</h1>
The remainder of this paper walks through the
standard library clauses and proposes wording changes to take advantage of template
deduction for class templates.
Even where no wording changes are required, we sometimes call out classes
that benefit from implicitly
generated deduction guides. Note that library vendors may choose to add additional explicit
deduction guides to maintain the “as-if” rule. See §21 below for an example of this.
<h2>§17 [library]</h2>
Modify 17.5.4.2.1p2 [namespace.std] as follows:
<blockquote><ul><li>an explicit or partial specialization of any member class template of a standard library class or class
template.</li>
<li><span class="ins">a deduction guide for any standard library class template.</span></li></ul></blockquote>
This clause requires no deduction guides
because it specifies only C libraries and so no class templates are involved.
<h2>§18 [language.support]</h2>
No changes are required to §18 [language.support].
<p>
<b>Rationale:</b> All of the headers in §18 are listed in
“Table 30 — Language support library summary” in §18.1
[support.general]:
</p>
<table border="1"><tbody><tr><th></th><th>Subclause</th><th>Header(s)</th></tr>
<tr><td>18.2</td><td>Common definitions</td><td><tt><cstddef></tt></td></tr>
<tr><td>18.3</td><td>Implementation properties</td><td><tt><limits><br><climits><br><cfloat></tt></td></tr><tr><td>18.4</td><td>Integer types</td><td><tt><cstdint></tt></td></tr>
<tr><td>18.5</td><td>Start and termination</td><td><tt><cstdlib></tt></td></tr>
<tr><td>18.6</td><td>Dynamic memory management</td><td><tt><new></tt></td></tr>
<tr><td>18.7</td><td>Type identification</td><td><tt><typeinfo></tt></td></tr>
<tr><td>18.8</td><td>Exception handling</td><td><tt><exception></tt></td></tr>
<tr><td>18.9</td><td>Initializer lists</td><td><tt><initializer_list></tt></td></tr>
<tr><td>18.10</td><td>Other runtime support</td><td><tt><csignal><br><csetjmps><br><cstdalign><br><cstdarg><br><cstdbool><br><cstdlib></tt></td></tr>
</tbody></table>
<h3><tt><limits></tt></h3>
The only class template in <tt><limits></tt>
is <tt>numeric_limits</tt>.
It has no non-default constructors (and only static members),
so no changes are needed.
<h3><tt><intializer_list></tt></h3>
The <initializer_list> class template
has only a default constructor
and “magic” construction
(from braced initializer lists)
that already does template constructor deduction,
so no changes are required.
<h3>Remaining headers in this clause</h3>
None of the <tt><c…></tt> headers or <tt><new></tt>,
<tt><typeinfo></tt>, or <tt><exception></tt> define class templates,
so they are unaffected by template constructor deduction.
<h2>§19 [diagnostics]</h2>
No changes are required to §19 [diagnostics].<p>
<b>Rationale:</b> All of the headers in §19 are listed in
“Table 31 — Diagnostics library summary” in §19.1:
</p><table border="1"><tbody><tr><th></th><th>Subclause</th><th>Header(s)</th></tr>
<tr><td>19.2</td><td>Exception classes</td><td><tt><stdexcept></tt></td></tr>
<tr><td>19.3</td><td>Assertions</td><td><tt><cassert></tt></td></tr>
<tr><td>19.4</td><td>Error numbers</td><td><tt><cerrno></tt></td></tr>
<tr><td>19.5</td><td>System error support</td><td><tt><system_error></tt></td></tr>
</tbody></table>
<h3><tt><stdexcept></tt>,
<tt><cassert></tt>,
<tt><cerrno></tt></h3>
<p>
None of these define any class templates,
so they are unaffected by template constructor deduction.
</p>
<h3><tt><system_error></tt></h3>
<p>
This header defines the class templates <tt>is_error_code_enum</tt>,
<tt>is_error_condition_enum</tt>,
and specializations of <tt>std::hash</tt>,
all of which have only default constructors.
</p>
<h2>§20 [utilities]</h2>
All of the headers in §20 are listed in
“Table 32 — General utilities library summary” in §20.1:
</p><table border="1"><tbody><tr><th></th><th>Subclause</th><th>Header(s)</th></tr>
<tr><td>20.2</td><td>Utilities components</td><td><tt><utility></tt></td></tr>
<tr><td>20.3</td><td>Compile-time integer sequences</td><td><tt><utility></tt></td></tr>
<tr><td>20.4</td><td>Pairs</td><td><tt><utility></tt></td></tr>
<tr><td>20.5</td><td>Tuples</td><td><tt><tuple></tt></td></tr>
<tr><td>20.6</td><td>Optional objects</td><td><tt><optional></tt></td></tr>
<tr><td>20.7</td><td>Variants</td><td><tt><variant></tt></td></tr>
<tr><td>20.8</td><td>Storage for any type</td><td><tt><any></tt></td></tr>
<tr><td>20.9</td><td>Fixed-size sequences of bits</td><td><tt><bitset></tt></td></tr>
<tr><td>20.10</td><td>Memory</td><td><tt><memory><br><cstdlib></tt></td></tr>
<tr><td>20.11</td><td>Smart pointers</td><td><tt><memory></tt></td></tr>
<tr><td>20.12</td><td>Memory resources</td><td><tt><memory_resource></tt></td></tr>
<tr><td>20.13</td><td>Scoped allocators</td><td><tt><scoped_allocator></tt></td></tr>
<tr><td>20.14</td><td>Function objects</td><td><tt><functional></tt></td></tr>
<tr><td>20.15</td><td>Type traits</td><td><tt><type_traits></tt></td></tr>
<tr><td>20.16</td><td>Compile-time rational arithmetic</td><td><tt><ratio></tt></td></tr>
<tr><td>20.17</td><td>Time utilities</td><td><tt><chrono><br><ctime></tt></td></tr>
<tr><td>20.18</td><td>Type indexes</td><td><tt><typeindex></tt></td></tr>
<tr><td>20.19</td><td>Execution policies</td><td><tt><execution></tt></td></tr>
</tbody></table>
<h3>§20.2 [utility]</h3>
No changes are required in this subclause as it specifies no class templates.
<h3>§20.3 [intseq]</h3>
No changes are required in §20.3.
Although <tt>integer_sequence</tt> is a class template,
it has no non-default constructors.
Interestingly, while the name <tt>make_integer_sequence</tt>
“looks like” a make function,
which is what the paper is trying to replace,
it is actually a type and therefore a different beast altogether.
<h3>§20.4 [pairs]</h3>
Per LWG, we no longer propose that the pair constructor unwrap <tt>reference_wrapper</tt>. We do
add the following guide which handles some cases missed by the implicit guide, including: Non-copyable arguments
(<tt>tuple<const T&...></tt> is excluded from overload resolution for non-copyable types) and
array to pointer conversion. This draft adopts Zhihao Yuan's suggestion of taking template parameters
by value to automatically get the decay.<p>
Make the following change
to the definition
of <tt>std::pair</tt> in §20.4.2 [pairs.pair]:
<blockquote><pre> void swap(pair& p) noexcept(<em>see below</em>);
};
<span class="ins"> template<class T1, class T2>
pair(T1, T2) -> pair<T1, T2>;</span>
}</pre></blockquote>
</p><h3>§20.5 [tuple]</h3>
<tt>tuple</tt> is handled similarly to <tt>pair</tt>. To accomplish that,
make the following change
to the definition
of <tt>std::tuple</tt> in §20.5.2 [tuple.tuple]:
<blockquote><pre> void swap(tuple&) noexcept(<em>see below</em>);
};
<span class="ins"> template<class... UTypes>
tuple(UTypes...) -> tuple<UTypes...>;
template<class T1, class T2>
tuple(pair<T1, T2>) -> tuple<T1, T2>;
template<class Alloc, class... UTypes>
tuple(allocator_arg_t, Alloc, UTypes...) -> tuple<UTypes...>;
template<class Alloc, class T1, class T2>
tuple(allocator_arg_t, Alloc, pair<T1, T2>) -> tuple<T1, T2>;
template<class Alloc, class... UTypes>
tuple(allocator_arg_t, Alloc, tuple<UTypes...>) -> tuple<UTypes...>;</span>
}</pre></blockquote>
<h3>§20.6 [optional]</h3>
<tt>optional</tt> is handled similarly to pair. Modify §20.6.3 [optional.optional] as follows:
<blockquote><pre> T *val; <span class="comment">// exposition only</span>
};
<span class="ins">
template<class T> optional(T) -> optional<T>;</span></pre></blockquote>
<b>Note:</b> See the <a href="#Background">Background</a> above for additional
discussion of <tt>optional</tt>.
<h3>§20.7 [variant]</h3>
Because of P0510R0, <tt>variant</tt> is no longer SFINAE friendly and does not work
with constructor type deduction. Note that we do not lose too much from this because
<tt>variant</tt>'s <em>raison d'etre</em> is their ability to hold types beyond those they were
initialized with.
<h3>§20.8 [any]</h3>
No changes are required in §20.8
as it defines no class templates.
<h3>§20.9 [template.bitset]</h3>
No changes required in this subclause. It would be tempting to have <tt>bitset("01101"s)</tt>
deduce <tt>bitset<5></tt>. However, we feel this is best left for a future proposal, likely
after a clearer consensus around compile-time strings has been achieved.
<h3>§20.10 [memory]</h3>
<tt>allocator</tt> requires no changes as only the copy constructor is
appropriate for deduction.
<h3>§20.11 [smartptr]</h3>
<!-- STL wants as an = delete -->
The primary question we considered was whether code like the following should be valid:
<code>int *ip = new int();
unique_ptr uip{ip}; <scan class="comment">// Deduce unique_ptr<int></scan></code>
On the positive side, the code is natural, useful (although not at object creation, when <tt>make_unique</tt> is
preferable), and we have already received
a request from the community for it. The downside is that it will fail to deduce an array type
<code>int *ip = new int[5];
unique_ptr uip{ip}; <scan class="comment">// Still deduces unique_ptr<int></scan></code>
We choose not to allow this problem, so we require that such deductions be ill-formed. <p>
Modify §20.11.1.2.1p8 [unique.ptr.single.ctor] as follows:
<blockquote><em>Remarks:</em> If this constructor is instantiated with a pointer type or reference type for the template
argument <tt>D</tt>, the program is ill-formed. <span class="ins">If class template argument deduction (13.3.1.8)
would select the function template corresponding to this constructor, then the program is ill-formed.</span></blockquote>
Add the following paragraph after §20.11.1.2.1p14 [unique.ptr.single.ctor]:
<blockquote><span class="ins"><em>Remarks:</em>If class template argument deduction (13.3.1.8)
would select a function template corresponding to either of these constructors, then the program is ill-formed.</span></blockquote>
We handle <tt>shared_ptr</tt> the same as <tt>unique_ptr</tt>. Because the
an implicit guides from <tt>T *</tt> are non-deducible, we do not need to add special wording for those
constructors. We do not include
a guide for the aliasing constructor as unnecessary.<p>Make the following modifications to §20.11.2.2 [util.smartptr.shared]:
<blockquote><pre> template<class U> bool owner_before(const shared_ptr<U>& b) const;
template<class U> bool owner_before(const weak_ptr<U>& b) const;
};
<span class="ins">template <class T> shared_ptr(weak_ptr<T>) -> shared_ptr<T>;
template <class T, class D> shared_ptr(unique_ptr<T, D>) -> shared_ptr<T>;</span></pre></blockquote>
For <tt>weak_ptr</tt>, make the following modification to §20.11.2.3 [util.smartptr.weak]
<blockquote><pre> template<class U> bool owner_before(const weak_ptr<U>& b) const;
};
<span class="ins">template<class T> weak_ptr(shared_ptr<T>) -> weak_ptr<T>;</span></pre></blockquote>
<p>For completeness, <tt>owner_less</tt> relies on implicit deduction guides. <tt>enable_shared_from_this</tt> does
not really require any guides, but the implicit ones certainly do no harm.
<h3>§20.12 [memory.resource]</h3>
No changes are required in this subclause as the <tt>polymorphic_allocator<Tp></tt> constructors do not contain any information about <tt>Tp</tt> (except when constructed
from other <tt>polymorphic_allocator</tt> objects, in which case deduction is properly
done without any changes required).
<h3>§20.13 [allocator.adaptor]</h3>
We supply an explicit deduction guide so that <tt>scoped_allocator_adaptor</tt> can
deduce its outer allocator. At the end of the definition of class <tt>scoped_allocator_adaptor</tt>
in §20.13.1 [allocator.adaptor.syn], add
<blockquote><pre> scoped_allocator_adaptor select_on_container_copy_construction() const;
};
<span class="ins">template<class OuterAlloc, class... InnerAllocs> scoped_allocator_adaptor(OuterAlloc, InnerAllocs...)
-> scoped_allocator_adaptor<OuterAllocator, InnerAllocs...>;</span></pre></blockquote>If a different outer allocator is desired, then
it can still be specified explicitly.
<h3>§20.14 [function.objects]</h3>
<!-- STL only wants the first guide -->
<tt>reference_wrapper</tt> requires the following change to make sure <tt>reference_wrapper(T&)</tt> doesn't
beat the copy constructor due to better conversions. Add the following deduction guide at the end
of the definition of class <tt>reference_wrapper</tt> in §20.14.5 [refwrap]
<blockquote><pre> operator() (ArgTypes&&...) const;
};
<span class="ins"> template<typename T>
reference_wrapper(reference_wrapper<T>) -> reference_wrapper<T>;</span></pre></blockquote>
We suggest allowing <tt>function</tt> to deduce its template argument when initialized
by a function. While it is tempting to add deduction guides for member pointers,
we no longer do so as there is a question about whether the first objects
should be a pointer or a reference. We are interested in committee feedback.
Note that we can always add this post-c++17.Add the following deduction guide at the end of the
class definition for <tt>function</tt> in §20.14.12.2 [func.wrap.func]
<blockquote><pre> template<class T> const T* target() const noexcept;
};
<span class="ins"> template<class R, class... ArgTypes>
function(R(*)(ArgTypes...)) -> function<R(ArgTypes...)>;
template<class F>
function(F) -> function<<span class="comment">see below</span>>;
</span></pre></blockquote>
Add a paragraph after §20.14.13.2.1p11 [func.wrap.func.con]
<blockquote><pre><span class="ins"> template<class F>
function(F) -> function<<span class="comment">see below</span>>;
</span></pre>
<blockquote><span class="ins"><em>Remarks:</em><blockquote><span class="ins">This deduction
guide participates in overload resolution only if <tt>&F::operator()</tt> is
well-formed when treated as an unevaluated operand. In that case, if <tt>decltype(&F::operator())</tt> is of the form
<tt>R(G::*)(A...) <em>cv</em> &<em><sub>opt</sub></em> noexcept<em><sub>opt</sub></em></tt> for
a class type <tt>G</tt>, then the deduced type shall be
<tt>function<R(A...)></tt>.</span></blockquote>
[<em>Example:</em><blockquote><pre><span class="ins">void f() {
int i{5};
function g = [&](double) { return i; }; <span class="comment">// Deduces <span style="font-style:normal"><tt>function<int(double)></tt></span></span>
}</span>
</pre></blockquote><em>—end example</em>] </span></blockquote></blockquote>
Add a new paragraph after 20.14.13.2p3 [func.wrap.func]:
<blockquote><span class="ins">[ <em>Note:</em> The types deduced by the
deduction guides for <tt>function</tt> may change in future versions of this International Standard.
—<em>end note</em>]</span></blockquote>
<b>Note:</b> There are some arbitrary choices in the deductions for member pointers. We
would be interested to see if the comittee agrees with having deduction guides for member
pointers in addition to function pointers, and if so, whether these are the right choices.<p>
Since template constructor deduction can be used to construct objects of type <tt>default_searcher</tt>, <tt>boyer_moore_searcher</tt>,
and <tt>boyer_moore_horspool_searcher</tt>, we propose getting rid of the searcher creation functions by
modifying §20.14p2 as follows:
</p><blockquote><pre> <span class="comment">// 20.14.13 searchers:</span>
template<class ForwardIterator, class BinaryPredicate = equal_to<>>
class default_searcher;
template<class RandomAccessIterator,
class Hash = hash<typename iterator_traits<RandomAccessIterator>::value_type>,
class BinaryPredicate = equal_to<>>
class boyer_moore_searcher;
template<class RandomAccessIterator,
class Hash = hash<typename iterator_traits<RandomAccessIterator>::value_type>,
class BinaryPredicate = equal_to<>>
class boyer_moore_horspool_searcher;
<span class="del"> template<class ForwardIterator, class BinaryPredicate = equal_to<>>
default_searcher<ForwardIterator, BinaryPredicate>
make_default_searcher(ForwardIterator pat_first, ForwardIterator pat_last,
BinaryPredicate pred = BinaryPredicate());
template<class RandomAccessIterator,
class Hash = hash<typename iterator_traits<RandomAccessIterator>::value_type>,
class BinaryPredicate = equal_to<>>
boyer_moore_searcher<RandomAccessIterator, Hash, BinaryPredicate>
make_boyer_moore_searcher(
RandomAccessIterator pat_first, RandomAccessIterator pat_last,
Hash hf = Hash(), BinaryPredicate pred = BinaryPredicate());
template<class RandomAccessIterator,
class Hash = hash<typename iterator_traits<RandomAccessIterator>::value_type>,
class BinaryPredicate = equal_to<>>
boyer_moore_searcher<RandomAccessIterator, Hash, BinaryPredicate>
make_boyer_moore_horspool_searcher(
RandomAccessIterator pat_first, RandomAccessIterator pat_last,
Hash hf = Hash(), BinaryPredicate pred = BinaryPredicate());</span>
<span class="comment">// 20.14.14, hash function primary template:</span>
</pre></blockquote>
Delete §20.14.13.1.1 [func.searchers.default.creation]
<blockquote><span class="del"><b>2014.13.2.1 <tt>boyer_moore_searcher</tt> creation functions [func.searcher.boyer_moore.creation]</b></span>
<pre><span class="del"> template<class ForwardIterator, class BinaryPredicate = equal_to<>>
default_searcher<ForwardIterator, BinaryPredicate>
make_default_searcher(ForwardIterator pat_first, RandomAccessIterator pat_last,
BinaryPredicate pred = BinaryPredicate());</span></pre>
<blockquote><span class="del"><em>Effects:</em> Equivalent to:</span><pre><span class="del">
return default_searcher<ForwardIterator, BinaryPredicate>(pat_first, pat_last, pred);</span></pre></blockquote></blockquote>
Delete §20.14.13.2.1 [func.searchers.boyer_moore.creation]
<blockquote><span class="del"><b>2014.13.2.1 <tt>boyer_moore_searcher</tt> creation functions [func.searcher.boyer_moore.creation]</b></span>
<pre><span class="del"> template<class RandomAccessIterator,
class Hash = hash<typename iterator_traits<RandomAccessIterator>::value_type>,
class BinaryPredicate = equal_to<>>
boyer_moore_searcher<RandomAccessIterator, Hash, BinaryPredicate>
make_boyer_moore_searcher(
RandomAccessIterator pat_first, RandomAccessIterator pat_last,
Hash hf = Hash(), BinaryPredicate pred = BinaryPredicate());</span></pre>
<blockquote><span class="del"><em>Effects:</em> Equivalent to:</span><pre><span class="del">
return boyer_moore_searcher<RandomAccessIterator, Hash, BinaryPredicate>(
pat_first, pat_last, hf, pred);</span></pre></blockquote></blockquote>
Delete §20.14.13.3.1 [func.searchers.boyer_moore_horspool.creation]
<blockquote><span class="del"><b>2014.13.2.1 <tt>boyer_moore_searcher</tt> creation functions [func.searcher.boyer_moore.creation]</b></span>
<pre><span class="del"> template<class RandomAccessIterator,
class Hash = hash<typename iterator_traits<RandomAccessIterator>::value_type>,
class BinaryPredicate = equal_to<>>
boyer_moore_horspool_searcher<RandomAccessIterator, Hash, BinaryPredicate>
make_boyer_moore_horspool_searcher(
RandomAccessIterator pat_first, RandomAccessIterator pat_last,
Hash hf = Hash(), BinaryPredicate pred = BinaryPredicate());</span></pre>
<blockquote><span class="del"><em>Effects:</em> Equivalent to:</span><pre><span class="del">
return boyer_moore_searcher<RandomAccessIterator, Hash, BinaryPredicate>(
pat_first, pat_last, hf, pred);</span></pre></blockquote></blockquote><p>
</p><h3>§20.15 [meta]</h3>
Since the classes in this subclause are designed primarily for compile-time metaprogramming, they do not have
constructors that require special treatment as a result of template deduction for constructors.
<h3>§20.16 [ratio]</h3>
Since the classes in this subclause are designed primarily for compile-time metaprogramming, they do not have
constructors that require special treatment as a result of template deduction for constructors.
<h3>§20.17 [time]</h3>
No wording changes necessary for §20.17 to leverage template
deduction for constructors. Note that LEWG voted against adding
a deduction guide to support expressions like <tt>duration(5L)</tt>.
<h3>§20.18 [type.index]</h3>
There are no class templates defined in this subclause, so nothing to do.
<h3>§20.19 [execpol]</h3>
The only class template in this subclause is the type trait <tt>is_execution_policy</tt>, so no changes are required as
described in §20.15 above.
<h2>§21 [strings]</h2>
The string library can take advantage of template argument deduction for constructors with few wording
changes. For example, <tt>basic_string_view("foo")</tt> correctly deduces that <tt>charT</tt> is <tt>char</tt>.
<p>It is worth noting that a library vendor may
choose to make additional deduction guides in accordance with the “as-if”
rule (§1.9 footnote 5) as illustrated by the following example. Suppose
a vendor has previously leveraged the
“as-if” rule to implement the constructor
<code>basic_string<charT, traits, Allocator>::basic_string(const charT* str, const Allocator& a = Allocator());</code> using the equivalent but non-deducible type <tt>value_type</tt> in place of <tt>charT</tt>
as follows:
<code>basic_string<charT, traits, Allocator>::basic_string(const value_type* str, const Allocator& a = Allocator());</code>
The vendor could maintain this convention while continuing to satisfy the “as-if” rule in C++17
by adding the following <em>deduction-guide</em> to their implementation:
<code>template<class charT, class traits = char_traits<charT>, class Allocator = allocator<charT>>
basic_string(const charT*, Allocator = Allocator()) -> basic_string<charT, Allocator>;</code>
Add the following after the end of the definition of class <tt>basic_string</tt> in §21.3.2 [basic.string]
<blockquote><pre> int compare(size_type pos1, size_type n1,
const charT* s, size_type n2) const;
};
<span class="ins"> template<class InputIterator, class Allocator = allocator<typename iterator_traits<InputIterator>::value_type>>
basic_string(InputIterator, InputIterator, Allocator = Allocator())
-> basic_string<typename iterator_traits<InputIterator>::value_type,
char_traits<typename iterator_traits<InputIterator>::value_type>, Allocator>;</span></pre></blockquote>
In §21.3.2.2 [string.cons], insert the following between paragraphs 19 and 20:
<blockquote><pre><span class="ins">template<class InputIterator, class Allocator = allocator<typename iterator_traits<InputIterator>::value_type>>
basic_string(InputIterator, InputIterator, Allocator = Allocator())
-> basic_string<typename iterator_traits<InputIterator>::value_type,
char_traits<typename iterator_traits<InputIterator>::value_type>, Allocator>;</span></pre>
<blockquote><span class="ins"><em>Remarks:</em> Shall not participate in overload resolution if <tt>InputIterator</tt> is
a type that does not qualify as an input iterator, or if <tt>Allocator</tt> is a type that does not qualify as an allocator [sequence.reqmts].</span></blockquote></blockquote>
<h2>§22 [localization]</h2>
Since <tt>wstring_convert</tt> and <tt>wbuffer_convert</tt> are deprecated,
we choose not to create deduction guides for them.
<h2>§23 [containers]</h2>
All of the headers in §23 are listed in
“Table 102 — Containers library summary” in §23.1:
<p></p><table border="1"><tbody><tr><th></th><th>Subclause</th><th>Header(s)</th></tr>
<tr><td>23.2</td><td>Requirements</td><td></td></tr>
<tr><td>23.3</td><td>Sequence containers</td><td><tt><array><br><deque><br><forward_list><br><list><br><vector></tt></td></tr>
<tr><td>23.4</td><td>Associative containers</td><td><tt><map><br><set></tt></td></tr>
<tr><td>23.5</td><td>Unordered associative containers</td><td><tt><unordered_map><br><unordered_set></tt></td></tr>
<tr><td>23.6</td><td>Container adaptors</td><td><tt><queue><br><stack></tt></td></tr>
</tbody></table>
Wording changes are needed in §23 for two purposes
<ol><li>Add deduction guides for constructing
containers from iterators as described in “Explicitly specified Deduction Guides”
in <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0091r3.html">P0091R3</a></li>
<li>Prevent allocators from confusing things (as is their wont). As Zhihao Yuan has pointed out,
with only implicit guides,
<span style="white-space:nowrap"><tt>vector(5, allocator<int>())</tt></span> would, presumably unintentionally, deduce
<tt>vector<allocator<int>></tt></li></ol>
but we have to make those changes many times as follows:
<h3>§23.2 [container.requirements]</h3>
Modify the end of §23.2.3/13 [sequence.reqmts] and the following paragraph as follows:
<blockquote>are called with a type <tt>InputIterator</tt> that does not qualify as an input iterator,
then those functions shall not participare in overload resolution.<p>
<span class="ins">— A deduction guide for a sequence container shall not participate in overload
resolution if it has an <tt>InputIterator</tt> template parameter that is called with a type that
does not qualify as an input iterator, or if it has an <tt>Allocator</tt> template
parameter that is called with a type that does not qualify as an allocator.</span>
<p>The extent to which an implementation determines that a type cannot be an input iterator is
unspecified, except that as a minimum integral types shall not qualify as input iterators.
<span class="ins">Likewise, the extent to which an implementation determines that a type
cannot be an allocator is unspecified, except that as a minimum a type
<tt>A</tt> not
satisfying both of
the following conditions shall not qualify as an allocator:
<ul><li><span class="ins">The <em>qualified-id</em>
<tt>A::value_type</tt> is valid and denotes a type [temp.deduct]</span></li>
<li><span class="ins">The expression <tt>declval<A&>().allocate(size_t{})</tt> is well-formed when treated as an unevaluated operand</span></li></ul></span></blockquote>
Add a paragraph to the end of §23.2.6 [associative.reqmts]
<blockquote><div class="ins">A deduction guide for an associative container shall not participate in overload resolution if
any of the following are true:<ul><li>It
has an <tt>InputIterator</tt> template
parameter that is called with a type that does not qualify as an input iterator</li>
<li>It has an <tt>Allocator</tt>
template parameter that is called with a type that does not qualify as an allocator</li>
<li>It has a <tt>Compare</tt> template parameter that is called with a type that qualifies as an allocator</li></ul>
</div></blockquote>
Add a paragraph to the end of §23.2.7 [unord.req]
<blockquote><div class="ins">A deduction guide for an unordered associative container shall not participate in overload resolution if any
of the following are true: <ul><li>It
has an <tt>InputIterator</tt> template
parameter that is called with a type that does not qualify as an input iterator</li><li>It has an <tt>Allocator</tt>
template parameter that is called with a type that does not qualify as an allocator</li>
<li>It has a <tt>Hash</tt> template parameter that is called with an
integral type or a type that qualifies as an allocator</li>
<li>It has a <tt>Pred</tt> template parameter
that is called with a type that qualifies as an allocator</li>
</ul></div></blockquote>
<b>Note: </b> The reason to ensure that <tt>Hash</tt> is not integral is
to keep it from matching the <tt>size_type</tt> that some constructors
use to specify the number of hash buckets.
<h3>§23.3 [sequences]</h3>
For <tt>std::array</tt>, based on considerations from p0511r1,
at the end of the definition of class <tt>array</tt> in 23.3.7.1 [array.overview],
we add the following <em>deduction-guide</em>:
<blockquote><pre> constexpr const T * data() const noexcept;
};
<span class="ins"> template <class T, class... U>
array(T, U...) -> array<T, 1 + sizeof...(U)>;</span>
}
</pre></blockquote>
Add the following paragraph to the end of 23.3.7.2 [array.cons]
<blockquote><pre><span class="ins"> template <class T, class... U>
array(T, U...) -> array<T, 1 + sizeof...(U)>;</span>
</pre><span class="ins"><em>Requires: </em>
<tt>(is_same_v<T, U> && ...)</tt> is <tt>true</tt>. Otherwise
the program is ill-formed.</span>
</blockquote>
At the end of the definition of class <tt>deque</tt> in §23.3.8.1 [deque.overview],
add the following <em>deduction-guide</em>:
<blockquote><pre> void clear() noexcept;
};
<!-- STL: Value type is guaranteed to be accessible. Simplify without allocator_traits -->
<span class="ins"> template <class InputIterator, class Allocator = allocator<typename iterator_traits<InputIterator>::value_type>>
deque(InputIterator, InputIterator, Allocator = Allocator())
-> deque<typename iterator_traits<InputIterator>::value_type, Allocator>;</span></pre></blockquote>
At the end of the definition of class <tt>forward_list</tt> in §23.3.9.1 [forwardlist.overview],
add the following <em>deduction-guide</em>:
<blockquote><pre> void reverse() noexcept;
};
<span class="ins"> template <class InputIterator, class Allocator = allocator<typename iterator_traits<InputIterator>::value_type>>
forward_list(InputIterator, InputIterator, Allocator = Allocator())
-> forward_list<typename iterator_traits<InputIterator>::value_type, Allocator>;</span></pre></blockquote>
At the end of the definition of class <tt>list</tt> in §23.3.10.1 [list.overview],
add the following <em>deduction-guide</em>s:
<blockquote><pre> void reverse() noexcept;
};
<span class="ins"> template <class InputIterator, class Allocator = allocator<typename iterator_traits<InputIterator>::value_type>>
list(InputIterator, InputIterator, Allocator = Allocator())
-> list<typename iterator_traits<InputIterator>::value_type, Allocator>;</span></pre></blockquote>
At the end of the definition of class <tt>vector</tt> in §23.3.11.1 [vector.overview],
add the following <em>deduction-guide</em>:
<blockquote><pre> void clear() noexcept;
};
<span class="ins"> template <class InputIterator, class Allocator = allocator<typename iterator_traits<InputIterator>::value_type>>
vector(InputIterator, InputIterator, Allocator = Allocator())
-> vector<typename iterator_traits<InputIterator>::value_type, Allocator>;</span></pre></blockquote>
Note that with the above guides <tt>vector<bool></tt> behaves properly as well.
<h3>§23.4 [associative]</h3>
First, we note that associative containers cannot always deduce their template parameters from an initializer list as illustrated by
the following code.
<code>map m = {{"foo", 2}, {"bar", 3}, {"baz", 4}}; <span class="comment">// Error: initializer_list not reified in type system</span>
map m2 = initializer_list<pair<char const *, int>>({{"foo", 2}, {"bar", 3}, {"baz", 4}}); <span class="comment">// OK </span></code>
Hopefully, this may be addressed by a future language extension in the post-C++17 timeline. Note also
that we apply <tt>remove_const_t</tt> to the keys in order to find the proper comparator (or hash in case
of unordered containers).<p>
Add a paragraph to §23.4.1 [associative.general]
<blockquote><span class="ins">The following exposition only type aliases may appear in deduction guides
for associative containers:</span>
<pre><span class="ins"> template<class InputIterator>
using iter_key_t = remove_const_t<typename iterator_traits<InputIterator>::value_type::first_type>; <span class="comment">// exposition only</span>
template<class InputIterator>
using iter_val_t = typename iterator_traits<InputIterator>::value_type::second_type; <span class="comment">// exposition only</span>
template<class InputIterator>
using iter_to_alloc_t = pair<add_const_t<typename iterator_traits<InputIterator>::value_type::first_type>,
typename iterator_traits<InputIterator>::value_type::second_type></span> <span class="comment">// exposition only</span></pre>
</blockquote>
At the end of the definition of class <tt>map</tt> in §23.4.4.1 [map.overview],
add the following <em>deduction-guide</em>s:
<blockquote><pre> template <class K>
pair<const_iterator, const_iterator> equal_range(const K& x) const;
};
<span class="ins"> template <class InputIterator,
class Compare = less<iter_key_t<InputIterator>>,
class Allocator = allocator<iter_to_alloc_t<InputIterator>>>
map(InputIterator, InputIterator, Compare = Compare(), Allocator = Allocator())
-> map<iter_key_t<InputIterator>, iter_val_t<InputIterator>, Compare, Allocator>;
template<class Key, class T, class Compare = less<Key>, class Allocator = allocator<pair<const Key, T>>>
map(initializer_list<pair<const Key, T>>, Compare = Compare(), Allocator = Allocator())
-> map<Key, T, Compare, Allocator>;
template <class InputIterator, class Allocator>
map(InputIterator, InputIterator, Allocator)
-> map<iter_key_t<InputIterator>, iter_val_t<InputIterator>, less<iter_key_t<InputIterator>>, Allocator>;
template<class Key, class T, class Allocator>
map(initializer_list<pair<const Key, T>>, Allocator) -> map<Key, T, less<Key>, Allocator>;</span></pre>
</blockquote>
<!-- Note: The need for the first deduction guide above is still under discussion -->
At the end of the definition of class <tt>multimap</tt> in §23.4.5.1 [multimap.overview],
add the following <em>deduction-guide</em>s:
</p><blockquote><pre> template <class K>
pair<const_iterator, const_iterator> equal_range(const K& x) const;
};
<span class="ins"> template <class InputIterator,
class Compare = less<iter_key_t<InputIterator>>,
class Allocator = allocator<iter_to_alloc_t<InputIterator>>>
multimap(InputIterator, InputIterator, Compare = Compare(), Allocator = Allocator())
-> multimap<iter_key_t<InputIterator>, iter_val_t<InputIterator>, Compare, Allocator>;
template<class Key, class T, class Compare = less<Key>, class Allocator = allocator<pair<const Key, T>>>
multimap(initializer_list<pair<const Key, T>>, Compare = Compare(), Allocator = Allocator())
-> multimap<Key, T, Compare, Allocator>;
template <class InputIterator, class Allocator>
multimap(InputIterator, InputIterator, Allocator)
-> multimap<iter_key_t<InputIterator>, iter_val_t<InputIterator>, less<iter_key_t<InputIterator>>, Allocator>;
template<class Key, class T, class Allocator>
multimap(initializer_list<pair<const Key, T>>, Allocator) -> multimap<Key, T, less<Key>, Allocator>;</span></pre></blockquote>
At the end of the definition of class <tt>set</tt> in §23.4.6.1 [set.overview],
add the following <em>deduction-guide</em>s:
<blockquote><pre> template <class K>
pair<const_iterator, const_iterator> equal_range(const K& x) const;
};
<span class="ins"> template <class InputIterator,
class Compare = less<typename iterator_traits<InputIterator>::value_type>,
class Allocator = allocator<typename iterator_traits<InputIterator>::value_type>>
set(InputIterator, InputIterator,
Compare = Compare(), Allocator = Allocator())
-> set<typename iterator_traits<InputIterator>::value_type, Compare, Allocator>;
template<class Key, class Compare = less<Key>, class Allocator = allocator<Key>>
set(initializer_list<Key>, Compare = Compare(), Allocator = Allocator())
-> set<Key, Compare, Allocator>;
template<class InputIterator, class Allocator>
set(InputIterator, InputIterator, Allocator)
-> set<typename iterator_traits<InputIterator>::value_type,
less<typename iterator_traits<InputIterator>::value_type>, Allocator>;
template<class Key, class Allocator>
set(initializer_list<Key>, Allocator) -> set<Key, less<Key>, Allocator>;
</span></pre></blockquote>
At the end of the definition of class <tt>multiset</tt> in §23.4.7.1 [multiset.overview],
add the following <em>deduction-guide</em>:
<blockquote><pre> template <class K>
pair<const_iterator, const_iterator> equal_range(const K& x) const;
};
<span class="ins"> template <class InputIterator,
class Compare = less<typename iterator_traits<InputIterator>::value_type>,
class Allocator = allocator<typename iterator_traits<InputIterator>::value_type>>
multiset(InputIterator, InputIterator,
Compare = Compare(), Allocator = Allocator())
-> multiset<typename iterator_traits<InputIterator>::value_type, Compare, Allocator>;
template<class Key, class Compare = less<Key>, class Allocator = allocator<Key>>
multiset(initializer_list<Key>, Compare = Compare(), Allocator = Allocator())
-> multiset<Key, Compare, Allocator>;
template<class InputIterator, class Allocator>
multiset(InputIterator, InputIterator, Allocator)
-> multiset<typename iterator_traits<InputIterator>::value_type,
less<typename iterator_traits<InputIterator>::value_type>, Allocator>;
template<class Key, class Allocator>
multiset(initializer_list<Key>, Allocator) -> multiset<Key, less<Key>, Allocator>;
</span></pre></blockquote>
<h3>§23.5 [unord]</h3>
Add a paragraph to the end of §23.5.1 [unord.general]:
<blockquote><span class="ins">The exposition only type aliases <tt>iter_key_t</tt>,
<tt>iter_val_t</tt>, and <tt>iter_to_alloc_t</tt> defined
in [associative.general] may appear in deduction guides for unordered containers</span></blockquote>
At the end of the definition of class <tt>unordered_map</tt> in §23.5.4.1 [unord.map.overview],
add the following <em>deduction-guide</em>s:
<blockquote><pre> void reserve(size_type n);
};
<span class="ins"> template<class InputIterator,
class Hash = hash<iter_key_t<InputIterator>>, class Pred = equal_to<iter_key_t<InputIterator>>,
class Allocator = allocator<iter_to_alloc_t<InputIterator>>>
unordered_map(InputIterator, InputIterator, typename <span class="comment">see below</span>::size_type = <span class="comment">see below</span>,
Hash = Hash(), Pred = Pred(), Allocator = Allocator())
-> unordered_map<iter_key_t<InputIterator>, iter_value_t<InputIterator>, Hash, Pred, Allocator>;
template<class Key, class T, class Hash = hash<Key>,
class Pred = equal_to<Key>, class Allocator = allocator<pair<const Key, T>>>
unordered_map(initializer_list<pair<const Key, T>>, typename <span class="comment">see below</span>::size_type = <span class="comment">see below</span>,
Hash = Hash(), Pred = Pred(), Allocator = Allocator())
-> unordered_map<Key, T, Hash, Pred, Allocator>;
template<class InputIterator, class Allocator>
unordered_map(InputIterator, InputIterator, typename <span class="comment">see below</span>::size_type, Allocator)
-> unordered_map<iter_key_t<InputIterator>, iter_val_t<InputIterator>,
hash<iter_key_t<InputIterator>>, equal_to<iter_key_t<InputIterator>>, Allocator>;
template<class InputIterator, class Allocator>
unordered_map(InputIterator, InputIterator, Allocator)
-> unordered_map<iter_key_t<InputIterator>, iter_val_t<InputIterator>,
hash<iter_key_t<InputIterator>>, equal_to<iter_key_t<InputIterator>>, Allocator>;
template<class InputIterator, class Hash, class Allocator>
unordered_map(InputIterator, InputIterator, typename <span class="comment">see below</span>::size_type, Hash, Allocator)
-> unordered_map<iter_key_t<InputIterator>, iter_val_t<InputIterator>, Hash,
equal_to<iter_key_t<InputIterator>>, Allocator>;
template<class Key, class T, typename Allocator>
unordered_map(initializer_list<pair<const Key, T>>, typename <span class="comment">see below</span>::size_type, Allocator)
-> unordered_map<Key, T, hash<Key>, equal_to<Key>, Allocator>;
template<class Key, class T, typename Allocator>
unordered_map(initializer_list<pair<const Key, T>>, Allocator)
-> unordered_map<Key, T, hash<Key>, equal_to<Key>, Allocator>;
template<class Key, class T, class Hash, class Allocator>
unordered_map(initializer_list<pair<const Key, T>>, typename <span class="comment">see below</span>::size_type, Hash, Allocator)
-> unordered_map<Key, T, Hash, equal_to<Key>, Allocator>;
</span>
</pre>
</blockquote>
Add the following paragraph to the end of §23.5.4.1 [unord.map.overview]:
<blockquote><span class="ins">A <tt>size_type</tt> parameter type in an <tt>unordered_map</tt> deduction
guide refers to the <tt>size_type</tt> member type of the type deduced by the deduction guide.</span></blockquote>
At the end of the definition of class <tt>unordered_multimap</tt> in §23.5.5.1 [unord.multimap.overview],
add the following <em>deduction-guide</em>s
</p><blockquote><pre> void reserve(size_type n);
};
<span class="ins"> template<class InputIterator,
class Hash = hash<iter_key_t<InputIterator>>, class Pred = equal_to<iter_key_t<InputIterator>>,
class Allocator = allocator<iter_to_alloc_t<InputIterator>>>
unordered_multimap(InputIterator, InputIterator, typename <span class="comment">see below</span>::size_type = <span class="comment">see below</span>,
Hash = Hash(), Pred = Pred(), Allocator = Allocator())
-> unordered_multimap<iter_key_t<InputIterator>, iter_value_t<InputIterator>, Hash, Pred, Allocator>;
template<class Key, class T, class Hash = hash<Key>,
class Pred = equal_to<Key>, class Allocator = allocator<pair<const Key, T>>>
unordered_multimap(initializer_list<pair<const Key, T>>, typename <span class="comment">see below</span>::size_type = <span class="comment">see below</span>,
Hash = Hash(), Pred = Pred(), Allocator = Allocator())
-> unordered_multimap<Key, T, Hash, Pred, Allocator>;
template<class InputIterator, class Allocator>
unordered_multimap(InputIterator, InputIterator, typename <span class="comment">see below</span>::size_type, Allocator)
-> unordered_multimap<iter_key_t<InputIterator>, iter_val_t<InputIterator>,
hash<iter_key_t<InputIterator>>, equal_to<iter_key_t<InputIterator>>, Allocator>;
template<class InputIterator, class Allocator>
unordered_multimap(InputIterator, InputIterator, Allocator)
-> unordered_multimap<iter_key_t<InputIterator>, iter_val_t<InputIterator>,
hash<iter_key_t<InputIterator>>, equal_to<iter_key_t<InputIterator>>, Allocator>;
template<class InputIterator, class Hash, class Allocator>
unordered_multimap(InputIterator, InputIterator, typename <span class="comment">see below</span>::size_type, Hash, Allocator)
-> unordered_multimap<iter_key_t<InputIterator>, iter_val_t<InputIterator>, Hash,
equal_to<iter_key_t<InputIterator>>, Allocator>;
template<class Key, class T, typename Allocator>
unordered_multimap(initializer_list<pair<const Key, T>>, typename <span class="comment">see below</span>::size_type, Allocator)
-> unordered_multimap<Key, T, hash<Key>, equal_to<Key>, Allocator>;
template<class Key, class T, typename Allocator>
unordered_multimap(initializer_list<pair<const Key, T>>, Allocator)
-> unordered_multimap<Key, T, hash<Key>, equal_to<Key>, Allocator>;
template<class Key, class T, class Hash, class Allocator>
unordered_multimap(initializer_list<pair<const Key, T>>, typename <span class="comment">see below</span>::size_type, Hash, Allocator)
-> unordered_multimap<Key, T, Hash, equal_to<Key>, Allocator>;</span>
</pre>
</blockquote>
Add the following paragraph to the end of §23.5.5.1 [unord.multimap.overview]:
<blockquote><span class="ins">A <tt>size_type</tt> parameter type in an <tt>unordered_multimap</tt> deduction
guide refers to the <tt>size_type</tt> member type of the type deduced by deduction guide.</span></blockquote>
At the end of the definition of class <tt>unordered_set</tt> in §23.5.6.1 [unord.set.overview],
add the following <em>deduction-guide</em>s:
<blockquote><pre> void reserve(size_type n);
};
<span class="ins"> template<class InputIterator,
class Hash = hash<typename iterator_traits<InputIterator>::value_type>,
class Pred = equal_to<typename iterator_traits<InputIterator>::value_type>,
class Allocator = allocator<typename iterator_traits<InputIterator>::value_type>>
unordered_set(InputIterator, InputIterator, typename <em>see below</em>::size_type = <em>see below</em>,
Hash = Hash(), Pred = Pred(), Allocator = Allocator())
-> unordered_set<typename iterator_traits<InputIterator>::value_type,
Hash, Pred, Allocator>;
template<class T, class Hash = hash<T>,
class Pred = equal_to<T>, class Allocator = allocator<T>>
unordered_set(initializer_list<T>, typename <em>see below</em>::size_type = <em>see below</em>,
Hash = Hash(), Pred = Pred(), Allocator = Allocator())
-> unordered_set<T, Hash, Pred, Allocator>;
template<class InputIterator, class Allocator>
unordered_set(InputIterator, InputIterator, typename <em>see below</em>::size_type, Allocator)
-> unordered_set<typename iterator_traits<InputIterator>::value_type,
hash<typename iterator_traits<InputIterator>::value_type>,
equal_to<typename iterator_traits<InputIterator>::value_type>,
Allocator>;
template<class InputIterator, class Hash, class Allocator>
unordered_set(InputIterator, InputIterator, typename <em>see below</em>::size_type,
Hash, Allocator)
-> unordered_set<typename iterator_traits<InputIterator>::value_type, Hash,
equal_to<typename iterator_traits<InputIterator>::value_type>,
Allocator>;
template<class T, class Allocator>
unordered_set(initializer_list<T>, typename <em>see below</em>::size_type, Allocator)
-> unordered_set<T, hash<T>, equal_to<T>, Allocator>;
template<class T, class Hash, class Allocator>
unordered_set(initializer_list<T>, typename <em>see below</em>::size_type, Hash, Allocator)
-> unordered_set<T, Hash, equal_to<T>, Allocator>;
</span>
</pre></blockquote>
Add the following paragraph to the end of §23.5.6.1 [unord.set.overview]:
<blockquote><span class="ins">A <tt>size_type</tt> parameter type in an <tt>unordered_set</tt> deduction
guide refers to the <tt>size_type</tt> member type of the primary <tt>unordered_set</tt> template.</span></blockquote>
At the end of the definition of class <tt>unordered_multiset</tt> in §23.5.7.1 [unord.multiset.overview],
add the following <em>deduction-guide</em>s:
<blockquote><pre> void reserve(size_type n);
};
<span class="ins"> template<class InputIterator,
class Hash = hash<typename iterator_traits<InputIterator>::value_type>,
class Pred = equal_to<typename iterator_traits<InputIterator>::value_type>,
class Allocator = allocator<typename iterator_traits<InputIterator>::value_type>>
unordered_multiset(InputIterator, InputIterator, <em>see below</em>::size_type = <em>see below</em>,
Hash = Hash(), Pred = Pred(), Allocator = Allocator())
-> unordered_multiset<typename iterator_traits<InputIterator>::value_type,
Hash, Pred, Allocator>;
template<class T, class Hash = hash<T>,
class Pred = equal_to<T>, class Allocator = allocator<T>>
unordered_multiset(initializer_list<T>, typename <em>see below</em>::size_type = <em>see below</em>,
Hash = Hash(), Pred = Pred(), Allocator = Allocator())
-> unordered_multiset<T, Hash, Pred, Allocator>;
template<class InputIterator, class Allocator>
unordered_multiset(InputIterator, InputIterator, typename <em>see below</em>::size_type, Allocator)
-> unordered_multiset<typename iterator_traits<InputIterator>::value_type,
hash<typename iterator_traits<InputIterator>::value_type>,
equal_to<typename iterator_traits<InputIterator>::value_type>,
Allocator>;
template<class InputIterator, class Hash, class Allocator>
unordered_multiset(InputIterator, InputIterator, typename <em>see below</em>::size_type,
Hash, Allocator)
-> unordered_multiset<typename iterator_traits<InputIterator>::value_type, Hash,
equal_to<typename iterator_traits<InputIterator>::value_type>, Allocator>;
template<class T, class Allocator>
unordered_multiset(initializer_list<T>, typename <em>see below</em>::size_type, Allocator)
-> unordered_multiset<T, hash<T>, equal_to<T>, Allocator>;
template<class T, class Hash, class Allocator>
unordered_multiset(initializer_list<T>, typename <em>see below</em>::size_type, Hash, Allocator)
-> unordered_multiset<T, Hash, equal_to<T>, Allocator>;
</span>
</pre></blockquote>
Add the following paragraph to the end of §23.5.7.1 [unord.multiset.overview]:
<blockquote><span class="ins">A <tt>size_type</tt> parameter type in an <tt>unordered_multiset</tt> deduction
guide refers to the <tt>size_type</tt> member type of the primary <tt>unordered_multiset</tt> template.</span></blockquote>
<h3>§23.6 [container.adaptors]</h3>
At the end of §23.6.1 [container.adaptors.general], and the following paragraph
<blockquote><div class="ins">A deduction guide for a container adaptor shall not participate in overload resolution if any
of the following are true: <ul><li>It
has an <tt>InputIterator</tt> template
parameter that is called with a type that does not qualify as an input iterator</li>
<li>It has a <tt>Compare</tt> template parameter that is called with a type that qualifies as an allocator</li>
<li>It has a <tt>Container</tt> template parameter that is called with a type that qualifies as an allocator</li>
<li>It has an <tt>Allocator</tt>
template parameter that is called with a type that does not qualify as an allocator</li>
<li>It has both <tt>Container</tt> and <tt>Allocator</tt> template parameters, and
<tt>uses_allocator_v<Container, Allocator></tt> is <tt>false</tt></li>
</ul></div></blockquote>
At the end of the definition of class <tt>queue</tt> in §23.6.4.1 [queue.defn] insert
<blockquote><pre> void swap(queue& q) noexcept(is_nothrow_swappable_v<Container>)
{ using std::swap; swap(c, q.c); }
};
<span class="ins"> template<class Container>
queue(Container) -> queue<typename Container::value_type, Container>;
template<class Container, class Allocator>
queue(Container, Allocator) -> queue<typename Container::value_type, Container>;
</span></pre></blockquote>
At the end of the definition of class <tt>priority_queue</tt> in §23.6.5
[priority.queue], add the following <em>deduction-guide</em>s:
<blockquote><pre> void swap(priority_queue& q) noexcept(is_nothrow_swappable_v<Container> &&
is_nothrow_swappable_v<Compare>)
{ using std::swap; swap(c, q.c); swap(comp, q.comp); }
};</pre></blockquote>
<blockquote><pre>
<span class="ins"> template <class Compare, class Container>
priority_queue(Compare, Container)
-> priority_queue<typename Container::value_type, Container, Compare>;
template<class InputIterator,
class Compare = less<typename iterator_traits<InputIterator>::value_type>,
class Container = vector<typename iterator_traits<InputIterator>::value_type>>
priority_queue(InputIterator, InputIterator, Compare = Compare(), Container = Container())
-> priority_queue<typename iterator_traits<InputIterator>::value_type, Container, Compare>;
template<class Compare, class Container, class Allocator>
priority_queue(Compare, Container, Allocator)
-> priority_queue<typename Container::value_type, Container, Compare>;
</span>
</pre></blockquote>
At the end of the definition of class <tt>stack</tt> in §23.6.6.1 [stack.defn], add
<blockquote><pre> void swap(stack& q) noexcept(is_nothrow_swappable_v<Container>)
{ using std::swap; swap(c, q.c); }
};
<span class="ins"> template<class Container>
stack(Container) -> stack<typename Container::value_type, Container>;
template<class Container, class Allocator>
stack(Container, Allocator) -> stack<typename Container::value_type, Container>;