forked from cplusplus/draft
-
Notifications
You must be signed in to change notification settings - Fork 2
/
d1144-object-relocation.bs
1182 lines (990 loc) · 53.3 KB
/
d1144-object-relocation.bs
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
<pre class='metadata'>
Title: std::is_trivially_relocatable
Shortname: D1144
Revision: 12
!Draft Revision: 71
Audience: EWGI
Status: D
Group: WG21
URL:
Editor: Arthur O'Dwyer, arthur.j.odwyer@gmail.com
Markup Shorthands: markdown yes, biblio yes, markup yes
Abstract:
P1144 trivial relocation is used by Abseil, AMC, BSL, Folly, HPX, Parlay, Pocketpy, Qt, Subspace, and Thrust.
Let's make it part of the C++ standard.
Date: 2024-10-15
</pre>
<style>
p {-moz-hyphens: none; -ms-hyphens: none; -webkit-hyphens: none; hyphens: none;}
ins {background-color: #CCFFCC; text-decoration: underline;}
del {background-color: #FFCACA; text-decoration: line-through;}
</style>
# Changelog # {#changelog}
- R12 (pre-Wrocław 2024):
- Complete rewrite of the prose sections.
- Added missing forward-declarations to [concepts.syn], [meta.type.synop], and [memory.syn].
- Removed `[[nodiscard]]` from `relocate(T*)`,
thanks to <a href="https://github.com/cplusplus/papers/issues/1744">P2422</a>.
- Updated [concept.relocatable]: `u2` mustn't be a potentially overlapping subobject.
- Updated [uninitialized.relocate] and [specialized.relocate]: Instead of "side effects <i>might</i> not happen,"
we now say "<i>do</i> not happen": Memmove optimization is now mandatory. (This addresses
one of EWG's concerns versus [[P2786]], that P1144 leaves too much up to quality-of-implementation.)
This incidentally guarantees that `relocate` of a trivially relocatable type will never throw.
# What's going on here? # {#intro}
<b>Isn't EWG already considering a "trivial relocation" proposal, [[P2786]]?</b>
Yes. P2786 was forwarded (1–8–3–3–1) from EWGI to EWG at Issaquah in February 2023.
P1144, which dates back to 2018, had <i>already</i> been voted out of EWGI once,
at Prague in February 2020 (1–3–4–1–0). It remains unclear why that vote was ignored.
At Issaquah, it was seen and voted <i>again</i> (0–7–4–3–1).
At Tokyo in February 2024, P2786 was voted from EWG into CWG (7–9–6–0–2).
But then, at St Louis in June 2024, EWG voted strongly (21–15–3–6–5) that P2786 wasn't ready for CWG after all,
and brought it back for further discussion. I <a href="https://wiki.edg.com/bin/view/Wg21stlouis2024/NotesEWGTrivialRelocatability">asked</a>
during that meeting whether the chair of EWG was willing to schedule P1144 for discussion,
or even to take a poll of EWG on <i>whether</i> to discuss it. He said no.
<b>That seems... weird. Is P2786 simply better?</b>
In my opinion, no it is not. It's more complicated and offers less to the programmer.
It has had no uptake in the programming community. In fact, the main reason it was so
overwhelmingly clawed back in St Louis is because of two papers presented there by
third-party library maintainers:
* [[P3233]] "Issues with P2786" (Giuseppe D'Angelo)
* [[P3236]] "Please reject P2786 and adopt P1144" (Stéphane Janel, Hans Goudey, Jacques Lucke, Alan de Freitas,
Krystian Stasiowski, Daniel Liam Anderson, Giuseppe Ottaviano, Giuseppe D’Angelo, Thiago Maciera,
Hartmut Kaiser, Isidoros Tsaousis, Shreyas Atre)
<b>Does P1144 have uptake in the community?</b>
Yes. In fact, since P1144R0 was modeled directly on Folly and BSL, you might say that
P1144 is the <i>committee's</i> uptake of a <i>community</i> idea!
Since 2018, most of the libraries that inspired P1144
have entrenched even further with its consistent terminology and semantics.
P1144R9 introduced a pair of feature-test macros, and some libraries have
adopted those macros, so that they <i>already today</i> get better performance on Arthur's
reference implementation and will be "ready on day one" when P1144 is eventually adopted
by the committee. The flagship examples are:
* Facebook Folly defines its `folly::IsRelocatable` trait in terms of P1144's
`std::is_trivially_relocatable<T>` if `__cpp_lib_trivially_relocatable` is defined.
Otherwise, Folly falls back on `is_trivially_copyable`.
* Stellar HPX defines `hpx::is_trivially_relocatable` in terms of P1144's
`std::is_trivially_relocatable<T>` if `HPX_HAVE_P1144_RELOCATE_AT` is defined
at build time.
* Google Abseil defines `absl::is_trivially_relocatable` with P1144 semantics.
Abseil will directly use Clang's `__is_trivially_relocatable(T)` builtin,
but not when compiled with Clang trunk — only if `__cpp_impl_trivially_relocatable` is defined.
([Godbolt.](https://godbolt.org/z/znMPE6hqv))
* Carnegie Mellon's ParlayLib project defines <a href="https://github.com/cmuparlay/parlaylib/blob/36459f4/include/parlay/type_traits.h#L250-L304"><code>parlay::is_trivially_relocatable</code></a>
in terms of P1144's `std::is_trivially_relocatable<T>` if `__cpp_lib_trivially_relocatable` is defined.
Otherwise, Parlay falls back on the Clang builtin.
<b>Wait. Clang has a builtin trait for this?</b>
Yes. That builtin was added to trunk by Devin Jeanpierre <a href="https://github.com/llvm/llvm-project/commit/19aa2db023c0128913da223d4fb02c474541ee22">in February 2022</a>,
about a year before P2786 was released to the public. The commit message indicated that
"rather than trying to pick a winning proposal for trivial relocation operations"
Clang would implement its own semantics, which turned out to be very similar to the semantics
chosen by P2786 the next year.
Sadly, Clang's chosen semantics have proven useless to many existing libraries. Folly, Abseil,
HPX, and Subspace all considered using Clang's builtin and decided against it, due to its
current semantics. Giuseppe D'Angelo, on the KDAB company blog, <a href="https://www.kdab.com/qt-and-trivial-relocation-part-5/">observes</a>:
> P2786’s design is limiting and not user-friendly, to the point that there have been
> serious concerns that existing libraries may not make use of it at all. In particular,
> P2786’s relocation semantics do not match Qt’s. With my Qt hat on, <i>it soon became
> clear that we could not have used P2786 in Qt to replace our own implementation of trivial relocation.</i>
[There was an effort in March 2024](https://github.com/llvm/llvm-project/pull/84621) to
give Clang trunk's `__is_trivially_relocatable(T)` P1144 semantics. The pull request was
supported with comments by maintainers of Abseil, Qt, AMC, Subspace, HPX, and
several smaller libraries as well.
As of this writing (October 2024), the pull request has not been accepted.
These libraries continue to rely on P1144's feature-test macros (or just use `is_trivially_copyable`),
because Clang trunk doesn't support their use-cases.
<b>And everyone just uses <code>memcpy</code> instead of <code>std::uninitialized_relocate</code>, right?</b>
Right. Many of them have implemented a P1144-alike API in <i>terms</i> of <code>memcpy</code>, though:
* Amadeus AMC's <a href="https://github.com/AmadeusITGroup/amc/blob/c38e46e/include/amc/memory.hpp#L500-L522"><code>amc::uninitialized_relocate</code></a>,
`uninitialized_relocate_n`, and `relocate_at`
* HPX's <a href="https://github.com/STEllAR-GROUP/hpx/blob/659e0ea/libs/core/type_support/include/hpx/type_support/uninitialized_relocation_primitives.hpp"><code>hpx::experimental::uninitialized_relocate</code></a>,
`uninitialized_relocate_n`, `uninitialized_relocate_backward`, and
<a href="https://github.com/STEllAR-GROUP/hpx/blob/bd32982/libs/core/type_support/include/hpx/type_support/relocate_at.hpp#L124-L133"><code>relocate_at</code></a>
* Parlay's <a href="https://github.com/cmuparlay/parlaylib/blob/36459f4/include/parlay/relocation.h"><code>uninitialized_relocate</code></a>
and `uninitialized_relocate_n`
* Qt's <a href="https://github.com/qt/qtbase/blob/cb40a1f/src/corelib/tools/qcontainertools_impl.h#L71-L87"><code>q_uninitialized_relocate_n</code></a>
<b>Could these two halves of the feature be severed?</b>
You mean, ship just the `is_trivially_relocatable<T>` trait in C++26, and then worry about the
algorithms like `uninitialized_relocate` (and the `trivially_relocatable` attribute itself) for C++29?
Sure, and I'd be fine with that — as long as the standard trait were defined in the P1144 way,
so that all these libraries can start using it.
<b>Hasn't P2786 adjusted its trait in that direction recently?</b>
Yes. Following EWG's clawback in St Louis 2024, P2786R7 decided that its `is_replaceable` trait should
consider the move-assignment operator as well as the move-constructor. That's a positive step. But, as
of this writing, P2786 still considers unannotated types "eligible for trivial relocation" when they have
a non-defaulted copy-constructor — whereas P1144 conservatively will not <i>assume</i> that any type is
trivially relocatable unless it is well-understood by the compiler (i.e., Rule of Zero).
Also, P2786 considers unannotated types "eligible for trivial relocation" even if they are polymorphic;
see [[Polymorphic]] for how that can cause segfaults in supposedly "well-defined" code.
Beyond the criteria for relocatability, P2786 has other unacceptable downsides. It bifurcates
the P1144 trait into two traits — `is_trivially_relocatable` and `is_replaceable`, where in fact the <i>latter</i>
corresponds to what everyone names `is_trivially_relocatable` today. That will lead to confusion.
P2786 invents new functions like `swap_value_representations` and `trivially_relocate`, again not reflecting
existing practice. `swap_value_representations` is defined to magically omit copying vptrs (even of
subobjects), which means different codegen for different "replaceable" types of the same size and alignment.
Contrariwise, P1144 allows us to share the same code for all trivially relocatable types of the same size, as seen
in <a href="https://godbolt.org/z/fxd7MY754">this Godbolt</a>. That's basically the point of calling the code "trivial"!
It is unambiguously a good thing every time P2786 takes a step toward P1144. But many of those steps remain to be taken.
<b>And EWG still refuses to directly discuss P1144 itself?</b>
So far, yes. I remain hopeful that one day that may change.
<b>Where can I learn more about trivial relocation?</b>
Besides <a href="https://quuxplusone.github.io/blog/tags/#relocatability">Arthur's blog</a>,
you might also want to look at:
* ["Trivially relocatable types in C++/Subspace"](https://orodu.net/2023/01/15/trivially-relocatable.html), by Dana Jansens
* ["Qt and trivial relocation"](https://www.kdab.com/qt-and-trivial-relocation-part-5/), by Giuseppe D'Angelo, on the KDAB blog
* ["Relocation semantics in the HPX library"](https://isidorostsa.github.io/gsoc2023/), by Isidoros Tsaousis
* ["Object relocation"](https://github.com/facebook/folly/blob/main/folly/docs/FBVector.md#object-relocation) in the Folly repository
# Proposed wording # {#wording}
The wording in this section is relative to the current working draft.
## [cpp.predefined] ## {#wording-cpp.predefined}
Add a feature-test macro to the table in
<a href="https://eel.is/c++draft/cpp.predefined#tab:cpp.predefined.ft">[cpp.predefined]</a>:
<small><blockquote>
<pre>
__cpp_impl_three_way_comparison 201907L
<ins>__cpp_impl_trivially_relocatable YYYYMML</ins>
__cpp_implicit_move 202207L
</pre>
</blockquote></small>
## [version.syn] ## {#wording-version.syn}
Add a feature-test macro to <a href="https://eel.is/c++draft/version.syn">[version.syn]/2</a>:
<small><blockquote>
<pre>
#define __cpp_lib_transparent_operators 201510L // freestanding, also in <memory>, <functional>
<ins>#define __cpp_lib_trivially_relocatable YYYYMML // freestanding, also in <memory>, <type_traits></ins>
#define __cpp_lib_tuple_element_t 201402L // freestanding, also in <tuple>
</pre>
</blockquote></small>
## [defns.relocation] ## {#wording-defns.relocation}
Add a new section in <a href="http://eel.is/c++draft/intro.defs">[intro.defs]</a>:
<small><blockquote>
<ins><b>relocation operation [defns.relocation]</b></ins>
<p> <ins>the homogeneous binary operation performed by `std::relocate_at`,
consisting of a move construction immediately followed by a destruction of the source object</ins>
</blockquote></small>
## [basic.types.general] ## {#wording-basic.types.general}
Add a new section in <a href="http://eel.is/c++draft/basic.types.general">[basic.types.general]</a>:
<small><blockquote>
9․ Arithmetic types ([basic.fundamental]), enumeration types, pointer types, pointer-to-member types ([basic.compound]),
`std::nullptr_t`, and <i>cv</i>-qualified versions of these types are collectively called <i>scalar types</i>.
Scalar types, trivially copyable class types ([class.prop]), arrays of such types, and <i>cv</i>-qualified versions
of these types are collectively called <i>trivially copyable types</i>.
Scalar types, trivial class types ([class.prop]), arrays of such types, and <i>cv</i>-qualified versions of these types
are collectively called <i>trivial types</i>. Scalar types, standard-layout class types ([class.prop]), arrays of such types,
and <i>cv</i>-qualified versions of these types are collectively called <i>standard-layout types</i>.
Scalar types, implicit-lifetime class types ([class.prop]), array types, and <i>cv</i>-qualified versions of these types
are collectively called <i>implicit-lifetime types</i>.
<p><ins>x․ Trivially copyable types, trivially relocatable class types (<a href="#wording-class.prop">[class.prop]</a>), arrays of such types,
and <i>cv</i>-qualified versions of these types are collectively called <i>trivially relocatable types</i>.
<p><ins>[*Note:* For a trivially relocatable type, the relocation operation (<a href="#wording-defns.relocation">[defns.relocation]</a>) as performed by,
for example, `std::swap_ranges` or `std::vector::reserve`, is tantamount
to a simple copy of the underlying bytes. *—end note*]</ins>
<p><ins>[*Note:* It is likely that many standard library types are trivially relocatable types. *—end note*]</ins>
10․ A type is a <i>literal type</i> if it is: [...]
</blockquote></small>
## [class.prop] ## {#wording-class.prop}
<p class="note"><b>DRAFTING NOTE:</b>
For the "if supported" wording, compare <a href="https://eel.is/c++draft/dcl.attr.nouniqueaddr#2.sentence-2">[dcl.attr.nouniqueaddr]/2</a>
and <a href="https://eel.is/c++draft/cpp.cond#5.sentence-1">[cpp.cond]/5</a>.
<p class="note"><b>DRAFTING NOTE:</b>
The wording proposed here deliberately echoes the existing "trivially copyable" wording.
"Copyable" and "relocatable" are siblings; every trivially copyable type is trivially relocatable by definition.
However, CWG already knows the wording for "trivially copyable" does not match library-writers' expectations;
see [[P3279]] for examples and a possible direction. If that direction is taken, then we'd certainly
update the proposed wording of "trivially relocatable" to follow the new wording of "trivially copyable."
Modify <a href="http://eel.is/c++draft/class.prop">[class.prop]</a> as follows:
<small><blockquote>
<p>1․ A <i>trivially copyable class</i> is a class:
- that has at least one eligible copy constructor, move constructor, copy assignment operator, or move assignment operator ([special], [class.copy.ctor], [class.copy.assign]),
- where each eligible copy constructor, move constructor, copy assignment operator, and move assignment operator is trivial, and
- that has a trivial, non-deleted destructor ([class.dtor]).
<p>2․ A <i>trivial class</i> is a class that is trivially copyable and has one or more eligible default constructors ([class.default.ctor]), all of which are trivial.
[*Note:* In particular, a trivially copyable or trivial class does not have virtual functions or virtual base classes. *— end note*]
<p><ins>x․ A <i>trivially relocatable class</i> is a class:
- <ins>where no eligible copy constructor, move constructor, copy assignment operator, move assignment operator, or destructor is user-provided,</ins>
- <ins>which has no virtual member functions or virtual base classes,</ins>
- <ins>all of whose non-static data members are either of reference type or of trivially relocatable type (<a href="#wording-basic.types.general">[basic.types.general]</a>), and</ins>
- <ins>all of whose base classes are of trivially relocatable type;</ins>
<ins>or a class that is declared with a `trivially_relocatable` attribute with value `true` (<a href="#wording-dcl.attr.trivreloc">[dcl.attr.trivreloc]</a>)
if that attribute is supported by the implementation (<a href="#wording-cpp.cond">[cpp.cond]</a>).</ins>
<p>3․ A class `S` is a <i>standard-layout class</i> if it: [...]
</blockquote></small>
## [dcl.attr.trivreloc] ## {#wording-dcl.attr.trivreloc}
<p class="note"><b>DRAFTING NOTE:</b>
For the "Recommended practice" wording, compare <a href="https://eel.is/c++draft/dcl.attr.nouniqueaddr#2.sentence-2">[dcl.attr.nouniqueaddr]/2</a>.
Add a new section after <a href="http://eel.is/c++draft/dcl.attr.nouniqueaddr">[dcl.attr.nouniqueaddr]</a>:
<small><blockquote>
<ins>1․ The *attribute-token* `trivially_relocatable` specifies that a class type's relocation operation has no
visible side-effects other than a copy of the underlying bytes, as if by the library function `std::memcpy`.
It may be applied to the definition of a class. It shall appear at most once in each *attribute-list*.
An *attribute-argument-clause* may be present and, if present, shall have the form</ins>
<pre>
<ins>( <i>constant-expression</i> )</ins>
</pre>
<ins>The *constant-expression* shall be an integral constant expression of type `bool`.
If no *attribute-argument-clause* is present, it has the same effect as an *attribute-argument-clause*
of `(true)`.</ins>
<p><ins>2․ If any definition of a class type has a `trivially_relocatable` attribute with value *V*, then each
definition of the same class type shall have a `trivially_relocatable` attribute with value *V*.
No diagnostic is required if definitions in different translation units have
mismatched `trivially_relocatable` attributes.</ins>
<p><ins>3․ If a class type is declared with the `trivially_relocatable` attribute, and the program relies on
observable side-effects of its relocation other than a copy of the underlying bytes, the behavior is undefined.</ins>
<p><ins>4․ *Recommended practice:* The value of a <i>has-attribute-expression</i> for
the `trivially_relocatable` attribute should be `0` for a given implementation unless this attribute
can cause a class type to be trivially relocatable (<a href="#wording-class.prop">[class.prop]</a>).</ins>
</blockquote></small>
## [cpp.cond] ## {#wording-cpp.cond}
Add a new entry to the table of supported attributes in
<a href="https://eel.is/c++draft/cpp.cond">[cpp.cond]</a>:
<small><blockquote>
<pre>
noreturn 200809L
<ins>trivially_relocatable YYYYMML</ins>
unlikely 201803L
</pre>
</blockquote></small>
## [concepts.syn] ## {#wording-concepts.syn}
Modify <a href="http://eel.is/c++draft/concepts.syn">[concepts.syn]</a> as follows:
<small><blockquote>
<pre>
<i>// [concept.copyconstructible], concept copy_constructible</i>
template<class T>
concept copy_constructible = <i>see below</i>;
<i>// <a href="#wording-concept.relocatable">[concept.relocatable]</a>, concept relocatable</i>
template<class T>
concept relocatable = <i>see below</i>;
</pre>
</blockquote></small>
## [concept.relocatable] ## {#wording-concept.relocatable}
<p class="note"><b>DRAFTING NOTE:</b>
We intend that a type may be relocatable
regardless of whether it is copy-constructible; but, if it is copy-constructible then copy-and-destroy
must have the same semantics as move-and-destroy. We intend that a type may be relocatable regardless of
whether it is assignable; but, if it is assignable then assignment must have the same semantics as
destroy-and-copy or destroy-and-move.
The semantic requirements on assignment help us optimize `vector::insert` and `vector::erase`.
`pmr::forward_list<int>` satisfies `relocatable`, but it models `relocatable`
only when all relevant objects have equal allocators.
Add a new section after <a href="http://eel.is/c++draft/concept.copyconstructible">[concept.copyconstructible]</a>:
<small><blockquote>
<ins><b>`relocatable` concept [concept.relocatable]</b></ins>
<p><pre>
<ins>template<class T></ins>
<ins>concept relocatable = move_constructible<T>;</ins>
</pre>
<p><ins>1․ If `T` is an object type, then let `rv` be an rvalue of type `T`, `lv` an lvalue of type `T` equal to `rv`,
and `u2` a distinct complete object of type `T` equal to `rv`.
`T` models `relocatable` only if</ins>
- <ins>After the definition `T u = rv;`, `u` is equal to `u2`.</ins>
- <ins>`T(rv)` is equal to `u2`.</ins>
- <ins>If the expression `u2 = rv` is well-formed, then the expression has the same semantics as
`u2.~T(); ::new ((void*)std::addressof(u2)) T(rv);`</ins>
- <ins>If the definition `T u = lv;` is well-formed, then after the definition `u` is equal to `u2`.</ins>
- <ins>If the expression `T(lv)` is well-formed, then the expression's result is equal to `u2`.</ins>
- <ins>If the expression `u2 = lv` is well-formed, then the expression has the same semantics as
`u2.~T(); ::new ((void*)std::addressof(u2)) T(lv);`</ins>
</blockquote></small>
## [memory.syn] ## {#wording-memory.syn}
Modify <a href="http://eel.is/c++draft/memory.syn">[memory.syn]</a> as follows:
<small><blockquote>
<pre>
template<class InputIterator, class NoThrowForwardIterator>
NoThrowForwardIterator uninitialized_move(InputIterator first, // freestanding
InputIterator last,
NoThrowForwardIterator result);
template<class ExecutionPolicy, class ForwardIterator, class NoThrowForwardIterator>
NoThrowForwardIterator uninitialized_move(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads]
ForwardIterator first, ForwardIterator last,
NoThrowForwardIterator result);
template<class InputIterator, class Size, class NoThrowForwardIterator>
pair<InputIterator, NoThrowForwardIterator>
uninitialized_move_n(InputIterator first, Size n, // freestanding
NoThrowForwardIterator result);
template<class ExecutionPolicy, class ForwardIterator, class Size,
class NoThrowForwardIterator>
pair<ForwardIterator, NoThrowForwardIterator>
uninitialized_move_n(ExecutionPolicy&& exec, // see [algorithms.parallel.overloads]
ForwardIterator first, Size n, NoThrowForwardIterator result);
namespace ranges {
template<class I, class O>
using uninitialized_move_result = in_out_result<I, O>; // freestanding
template<input_iterator I, sentinel_for<I> S1,
<i>nothrow-forward-iterator</i> O, <i>nothrow-sentinel-for</i><O> S2>
requires constructible_from<iter_value_t<O>, iter_rvalue_reference_t<I>>
uninitialized_move_result<I, O>
uninitialized_move(I ifirst, S1 ilast, O ofirst, S2 olast); // freestanding
template<input_range IR, <i>nothrow-forward-range</i> OR>
requires constructible_from<range_value_t<OR>, range_rvalue_reference_t<IR>>
uninitialized_move_result<borrowed_iterator_t<IR>, borrowed_iterator_t<OR>>
uninitialized_move(IR&& in_range, OR&& out_range); // freestanding
template<class I, class O>
using uninitialized_move_n_result = in_out_result<I, O>; // freestanding
template<input_iterator I,
<i>nothrow-forward-iterator</i> O, <i>nothrow-sentinel-for</i><O> S>
requires constructible_from<iter_value_t<O>, iter_rvalue_reference_t<I>>
uninitialized_move_n_result<I, O>
uninitialized_move_n(I ifirst, iter_difference_t<I> n, // freestanding
O ofirst, S olast);
}
<ins>template<class NoThrowInputIterator, class NoThrowForwardIterator></ins>
<ins>NoThrowForwardIterator uninitialized_relocate(NoThrowInputIterator first,</ins>
<ins>NoThrowInputIterator last,</ins>
<ins>NoThrowForwardIterator result);</ins> <ins>// freestanding</ins>
<ins>template<class ExecutionPolicy, class NoThrowForwardIterator1, class NoThrowForwardIterator2></ins>
<ins>NoThrowForwardIterator2 uninitialized_relocate(ExecutionPolicy&& exec,</ins> <ins>// see [algorithms.parallel.overloads]</ins>
<ins>NoThrowForwardIterator1 first, NoThrowForwardIterator1 last,</ins>
<ins>NoThrowForwardIterator2 result);</ins>
<ins>template<class NoThrowInputIterator, class Size, class NoThrowForwardIterator></ins>
<ins>pair<NoThrowInputIterator, NoThrowForwardIterator></ins>
<ins>uninitialized_relocate_n(NoThrowInputIterator first, Size n,</ins>
<ins>NoThrowForwardIterator result);</ins> <ins>// freestanding</ins>
<ins>template<class ExecutionPolicy, class NoThrowForwardIterator1, class Size,</ins>
<ins>class NoThrowForwardIterator2></ins>
<ins>pair<NoThrowForwardIterator1, NoThrowForwardIterator2></ins>
<ins>uninitialized_relocate_n(ExecutionPolicy&& exec,</ins> <ins>// see [algorithms.parallel.overloads]</ins>
<ins>NoThrowForwardIterator1 first, Size n, NoThrowForwardIterator2 result);</ins>
<ins>template<class NoThrowBidirectionalIterator1, class NoThrowBidirectionalIterator2></ins>
<ins>NoThrowBidirectionalIterator2</ins>
<ins>uninitialized_relocate_backward(NoThrowBidirectionalIterator1 first,</ins>
<ins>NoThrowBidirectionalIterator1 last,</ins>
<ins>NoThrowBidirectionalIterator2 result);</ins> <ins>// freestanding</ins>
<ins>template<class ExecutionPolicy, class NoThrowBidirectionalIterator1, class NoThrowBidirectionalIterator2></ins>
<ins>NoThrowBidirectionalIterator2</ins>
<ins>uninitialized_relocate_backward(ExecutionPolicy&& exec,</ins>
<ins>NoThrowBidirectionalIterator1 first,</ins>
<ins>NoThrowBidirectionalIterator1 last,</ins>
<ins>NoThrowBidirectionalIterator2 result);</ins> <ins>// freestanding</ins>
template<class NoThrowForwardIterator, class T>
void uninitialized_fill(NoThrowForwardIterator first, // freestanding
NoThrowForwardIterator last, const T& x);
[...]
template<<i>nothrow-input-iterator</i> I>
requires destructible<iter_value_t<I>>
constexpr I destroy_n(I first, iter_difference_t<I> n) noexcept; // freestanding
}
<ins><i>// <a href="#wording-specialized.relocate">[specialized.relocate]</a>, relocate</i></ins>
<ins>template<class T></ins>
<ins>T *relocate_at(T* source, T* dest);</ins> <ins>// freestanding</ins>
<ins>template<class T></ins>
<ins>remove_cv_t<T> relocate(T* source);</ins> <ins>// freestanding</ins>
// [unique.ptr], class template unique_ptr
</pre>
</blockquote></small>
## [meta.type.synop] ## {#wording-meta.type.synop}
Modify <a href="http://eel.is/c++draft/meta.type.synop">[meta.type.synop]</a> as follows:
<small><blockquote>
<pre>
[...]
<i>// <a href="#wording-meta.unary.prop">[meta.unary.prop]</a>, type properties</i>
template<class T> struct is_const;
template<class T> struct is_volatile;
template<class T> struct is_trivial;
template<class T> struct is_trivially_copyable;
<ins>template<class T> struct is_trivially_relocatable;</ins>
template<class T> struct is_standard_layout;
[...]
</pre>
</blockquote></small>
## [meta.unary.prop] ## {#wording-meta.unary.prop}
Add a new entry to Table 47 in <a href="http://eel.is/c++draft/meta.unary.prop">[meta.unary.prop]</a>:
<small><blockquote>
<table>
<tr><th>Template</th><th>Condition</th><th>Preconditions</th></tr>
<tr>
<td>`template<class T> struct is_trivially_copyable;`</td>
<td>`T` is a trivially copyable type ([basic.types.general])</td>
<td>`remove_all_extents_t<T>` shall be a complete type or <i>cv</i> `void`.</td>
</tr>
<tr>
<td><ins>`template<class T> struct is_trivially_relocatable;`</ins></td>
<td><ins>`T` is a trivially relocatable type (<a href="#wording-basic.types.general">[basic.types.general]</a>)</ins></td>
<td><ins>`remove_all_extents_t<T>` shall be a complete type or <i>cv</i> `void`.</ins></td>
</tr>
<tr>
<td>`template<class T> struct is_standard_layout;`</td>
<td>`T` is a standard-layout type ([basic.types.general])</td>
<td>`remove_all_extents_t<T>` shall be a complete type or <i>cv</i> `void`.</td>
</tr>
</table>
</blockquote></small>
## [algorithms.requirements] ## {#wording-algorithms.requirements}
Modify <a href="https://eel.is/c++draft/algorithms.requirements">[algorithms.requirements]</a> as follows:
<small><blockquote>
* If an algorithm's template parameter is named `InputIterator`, `InputIterator1`, <del>or</del> `InputIterator2`, <ins>or
`NoThrowInputIterator`,</ins> the template argument shall meet the *Cpp17InputIterator* requirements ([input.iterators]).
* If an algorithm's template parameter is named `OutputIterator`, `OutputIterator1`, or `OutputIterator2`, the template argument
shall meet the `Cpp17OutputIterator` requirements ([output.iterators]).
* If an algorithm's template parameter is named `ForwardIterator`, `ForwardIterator1`,
`ForwardIterator2`, <del>or</del> `NoThrowForwardIterator`, <ins>`NoThrowForwardIterator1`, or `NoThrowForwardIterator2`,</ins> the
template argument shall meet the *Cpp17ForwardIterator* requirements ([forward.iterators]) if it is required to be a mutable iterator,
or model `forward_iterator` ([iterator.concept.forward]) otherwise.
* If an algorithm's template parameter is
named <ins>`NoThrowInputIterator`,</ins> `NoThrowForwardIterator`, <ins>`NoThrowForwardIterator1`, or `NoThrowForwardIterator2`,</ins> the
template argument is also required to have the property that no exceptions are thrown
from increment, assignment, or comparison of, or indirection through, valid iterators.
* If an algorithm's template parameter is named `BidirectionalIterator`,
`BidirectionalIterator1`, <del>or</del> `BidirectionalIterator2`, <ins>`NoThrowBidirectionalIterator1`, or `NoThrowBidirectionalIterator2`,</ins> the
template argument shall meet the *Cpp17BidirectionalIterator* requirements ([bidirectional.iterators])
if it is required to be a mutable iterator, or model `bidirectional_iterator` ([iterator.concept.bidir]) otherwise.
* <ins>If an algorithm's template parameter is named `NoThrowBidirectionalIterator1` or `NoThrowBidirectionalIterator2`, the
template argument is also required to have the property that no exceptions are thrown
from increment, decrement, assignment, or comparison of, or indirection through, valid iterators.</ins>
</blockquote></small>
## [uninitialized.relocate] ## {#wording-uninitialized.relocate}
<p class="note"><b>DRAFTING NOTE:</b>
Compare to <a href="https://eel.is/c++draft/uninitialized.move">[uninitialized.move]</a> and
<a href="https://eel.is/c++draft/alg.copy">[alg.copy]</a>. The <i>Remarks</i> allude to blanket wording
in <a href="http://eel.is/c++draft/specialized.algorithms#general-2">[specialized.algorithms.general]/2</a>.
Add a new section after <a href="http://eel.is/c++draft/uninitialized.move">[uninitialized.move]</a>:
<small><blockquote>
<ins><b><code>uninitialized_relocate</code> [uninitialized.relocate]</b></ins>
<pre>
<ins>template<class NoThrowInputIterator, class NoThrowForwardIterator></ins>
<ins>NoThrowForwardIterator uninitialized_relocate(NoThrowInputIterator first, NoThrowInputIterator last,</ins>
<ins>NoThrowForwardIterator result);</ins>
</pre>
<p><ins>1․ *Effects:* Equivalent to:</ins>
<pre>
<ins>try {</ins>
<ins>for (; first != last; ++result, (void)++first) {</ins>
<ins>::new (<i>voidify</i>(*result))</ins>
<ins>typename iterator_traits<NoThrowForwardIterator>::value_type(std::move(*first));</ins>
<ins>destroy_at(addressof(*first));</ins>
<ins>}</ins>
<ins>return result;</ins>
<ins>} catch (...) {</ins>
<ins>destroy(++first, last);</ins>
<ins>throw;</ins>
<ins>}</ins>
</pre>
<p><ins>except that if the iterators' common value type is trivially relocatable (<a href="#wording-basic.types.general">[basic.types.general]</a>),
side effects associated with the relocation of values do not happen.</ins>
<p><ins>2․ *Remarks:* If an exception is thrown, all objects in both the source and destination
ranges are destroyed.</ins>
<pre>
<ins>template<class NoThrowInputIterator, class Size, class NoThrowForwardIterator></ins>
<ins>pair<NoThrowInputIterator, NoThrowForwardIterator></ins>
<ins>uninitialized_relocate_n(NoThrowInputIterator first, Size n, NoThrowForwardIterator result);</ins>
</pre>
<p><ins>3․ *Effects:* Equivalent to:</ins>
<pre>
<ins>try {</ins>
<ins>for (; n > 0; ++result, (void)++first, --n) {</ins>
<ins>::new (<i>voidify</i>(*result))</ins>
<ins>typename iterator_traits<NoThrowForwardIterator>::value_type(std::move(*first));</ins>
<ins>destroy_at(addressof(*first));</ins>
<ins>}</ins>
<ins>return {first, result};</ins>
<ins>} catch (...) {</ins>
<ins>destroy_n(++first, --n);</ins>
<ins>throw;</ins>
<ins>}</ins>
</pre>
<p><ins>except that if the iterators' common value type is trivially relocatable (<a href="#wording-basic.types.general">[basic.types.general]</a>),
side effects associated with the relocation of values do not happen.</ins>
<p><ins>4․ *Remarks:* If an exception is thrown, all objects in both the source and destination
ranges are destroyed.</ins>
<pre>
<ins>template<class NoThrowBidirectionalIterator1, class NoThrowBidirectionalIterator2></ins>
<ins>NoThrowBidirectionalIterator2</ins>
<ins>uninitialized_relocate_backward(NoThrowBidirectionalIterator1 first,</ins>
<ins>NoThrowBidirectionalIterator1 last,</ins>
<ins>NoThrowBidirectionalIterator2 result);</ins>
</pre>
<ins>5․ *Effects:* Equivalent to:</ins>
<pre>
<ins>try {</ins>
<ins>for (; last != first; ) {</ins>
<ins>--last;</ins>
<ins>--result;</ins>
<ins>::new (<i>voidify</i>(*result))</ins>
<ins>typename iterator_traits<NoThrowBidirectionalIterator2>::value_type(std::move(*last));</ins>
<ins>destroy_at(addressof(*last));</ins>
<ins>}</ins>
<ins>return result;</ins>
<ins>} catch (...) {</ins>
<ins>destroy(first, ++last);</ins>
<ins>throw;</ins>
<ins>}</ins>
</pre>
<p><ins>except that if the iterators' common value type is trivially relocatable (<a href="#wording-basic.types.general">[basic.types.general]</a>),
side effects associated with the relocation of values do not happen.</ins>
<p><ins>6․ *Remarks:* If an exception is thrown, all objects in both the source and destination
ranges are destroyed.</ins>
</blockquote></small>
## [specialized.relocate] ## {#wording-specialized.relocate}
Add a new section after <a href="http://eel.is/c++draft/specialized.destroy">[specialized.destroy]</a>:
<small><blockquote>
<ins><b>`relocate` [specialized.relocate]</b></ins>
<p><pre>
<ins>template<class T></ins>
<ins>T *relocate_at(T* source, T* dest);</ins>
</pre>
<p><ins>1․ *Mandates:* `T` is a complete non-array object type.</ins>
<p><ins>2․ *Effects:* Equivalent to:</ins>
<pre>
<ins>struct guard { T *t; ~guard() { destroy_at(t); } } g(source);</ins>
<ins>return ::new (<i>voidify</i>(*dest)) T(std::move(*source));</ins>
</pre>
<p><ins>except that if `T` is trivially relocatable (<a href="#wording-basic.types.general">[basic.types.general]</a>),
side effects associated with the relocation of the value of `*source` do not happen.</ins>
<pre>
<ins>template<class T></ins>
<ins>remove_cv_t<T> relocate(T* source);</ins>
</pre>
<p><ins>3․ *Mandates:* `T` is a complete non-array object type.</ins>
<p><ins>4․ *Effects:* Equivalent to:</ins>
<pre>
<ins>remove_cv_t<T> t = std::move(source);</ins>
<ins>destroy_at(source);</ins>
<ins>return t;</ins>
</pre>
<p><ins>except that if `T` is trivially relocatable (<a href="#wording-basic.types.general">[basic.types.general]</a>),
side effects associated with the relocation of the value of `*source` do not happen.</ins>
</blockquote></small>
# Acknowledgements # {#acknowledgements}
Thanks to Pablo Halpern for [[N4158]], to which this proposal bears a striking resemblance —
including the meaning assigned to the word "trivial," and the library-algorithm approach to avoiding the
problems with "lame duck objects" discussed in
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2002/n1377.htm#Alternative%20move%20designs">the final section</a>
of [[N1377]]. See <a href="http://wiki.edg.com/bin/view/Wg21rapperswil2014/N4034">discussion of N4034 at Rapperswil</a> (June 2014)
and <a href="http://wiki.edg.com/bin/view/Wg21urbana-champaign/EvolutionWorkingGroup#N4158_Destructive_Move_Rev_1">discussion
of N4158 at Urbana</a> (November 2014).
Significantly different approaches to this problem have previously appeared in Rodrigo Castro Campos's
[[N2754]], Denis Bider's [[P0023R0]] (introducing a core-language "relocation" operator), and
Niall Douglas's [[P1029R3]] (treating trivial relocatability as an aspect of move-construction in isolation,
rather than an aspect of the class type as a whole).
A less different approach is taken by Mungo Gill & Alisdair Meredith's [[P2786]].
[[P2814R1]] compares P2786R0 against P1144R8.
Thanks to Elias Kosunen, Niall Douglas, John Bandela, and Nicolas Lesser for their feedback on early drafts of P1144R0.
Thanks to Jens Maurer for his feedback on P1144R3 at Kona 2019, and to Corentin Jabot for championing
P1144R4 at Prague 2020.
Many thanks to Matt Godbolt for allowing me to install my Clang fork on Compiler Explorer
(<a href="https://p1144.godbolt.org/z/oWEd_X">godbolt.org</a>). See also [[Announcing]].
Thanks to Nicolas Lesser and John McCall for their review comments on the original Clang pull request [[D50119]].
Thanks to Amirreza Ashouri for reviving the Clang effort in 2024 as
<a href="https://github.com/llvm/llvm-project/pull/84621">#84621</a>, and to the dozens of GitHub users
who have starred and library maintainers who have commented in support of that review.
Thanks to Howard Hinnant for appearing with me on [[CppChat]] in 2018, and to Jon Kalb and Phil Nash for hosting us.
Thanks to Marc Glisse for his work integrating a "trivially relocatable" trait into GNU libstdc++ (see [[Deque]])
and for answering my questions on [GCC bug 87106](https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87106).
Thanks to Dana Jansens for her contributions re overlapping and non-standard-layout types (see [[Subspace]]),
to Alisdair Meredith for our extensive discussions during the February 2023 drafting of P2786R0,
and to Giuseppe D'Angelo for extensive review comments and discussion.
Thanks to Charles Salvia (`stdx::error`), Isidoros Tsaousis-Seiras (HPX), Orvid King (Folly),
Daniel Anderson (Parlay), and Derek Mauro (Abseil) for their work integrating P1144 into their
respective libraries. Special thanks to Stéphane Janel (AMC) for doing the work completely
independently, such that I only found out after the fact. :)
Thanks to Giuseppe D'Angelo for [[P3233]]. Thanks to
Alan de Freitas, Daniel Liam Anderson, Giuseppe D'Angelo, Hans Goudey, Hartmut Kaiser, Isidoros Tsaousis,
Jacques Lucke, Krystian Stasiowski, Shreyas Atre, Stéphane Janel, and Thiago Maciera for [[P3236]].
Thanks to... you? If you can help (by adding relevant support to your third-party library;
by submitting P1144-style optimizations to standard libraries; by writing a GCC patch;
by writing a blog post; in any other way), please reach out!
Appendix A: Straw polls {#polls}
=================================
## Poll taken in EWG at St Louis on 2024-06-28 ## {#taken-polls-2024-06-28}
Pablo Halpern presented [[P2786]] along with a sketch of P2786's roadmap to parity with P1144
(namely [[P2967]], [[P3239]], and [[D3262]]).
On the other side, Giuseppe D'Angelo presented [[P3233]] and [[P3236]].
<table class="def">
<tr><th style="width: 70%;"></th><th>**SF**</th><th>**F**</th><th>**N**</th><th>**A**</th><th>**SA**</th></tr>
<tr><th><small>Given the new information received (P3233R0, P3236R1, P3278R0), we wish to un-forward P2786 from CWG and bring it back to EWG.</th>
<th> 21 </th><th> 15 </th><th> 3 </th><th> 6 </th><th> 5 </th></tr>
</table>
## Polls taken in EWGI at Issaquah on 2023-02-10 ## {#taken-polls-2023-02-10}
Arthur O'Dwyer presented [[P1144R6]]. Alisdair Meredith presented
<a href="https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023/p2786r0.pdf">P2786R0</a> (which proposed a
`[[maybe_trivially_relocatable]]`-style facility, and expressed it as a contextual keyword instead
of an attribute). EWGI took the following [straw polls](https://wiki.edg.com/bin/view/Wg21issaquah2023/EWGIP1144R6)
(as well as polls on attribute syntax and on both papers' readiness for EWG).
<table class="def">
<tr><th style="width: 70%;"></th><th>**SF**</th><th>**F**</th><th>**N**</th><th>**A**</th><th>**SA**</th></tr>
<tr><th><small>The problem presented in P1144/P2786 is worth solving.</th>
<th> 10 </th><th> 8 </th><th> 0 </th><th> 0 </th><th> 0 </th></tr>
<tr><th><small>The problem being introduced in P1144/P2786 should be solved in a more general way instead of as proposed.</th>
<th> 3 </th><th> 0 </th><th> 5 </th><th> 6 </th><th> 4 </th></tr>
<tr><th><small>The annotation should "trust the user" as in P1144R6's `[[trivially_relocatable]]` ("sharp knife"),
instead of diagnosing as in P1144R6's `[[clang::maybe_trivially_relocatable]]` and P2786R0's `trivially_relocatable` ("dull knife"). Three-way poll.</th>
<th> — </th><th> 7 </th><th> 5 </th><th> 6 </th><th> — </th></tr>
<tr><th><small>Forward P1144 to EWG.</th>
<th> 0 </th><th> 7 </th><th> 4 </th><th> 3 </th><th> 1 </th></tr>
</table>
## Polls taken in EWGI at Prague on 2020-02-13 ## {#taken-polls-2020-02-13}
Corentin Jabot championed P1144R4. EWGI discussed P1144R4 and Niall Douglas's [[P1029R3]] consecutively,
then took the following [straw polls](https://wiki.edg.com/bin/view/Wg21prague/P1144R4SG17)
(as well as a poll on the attribute syntax).
<table class="def">
<tr><th style="width: 70%;"></th><th>**SF**</th><th>**F**</th><th>**N**</th><th>**A**</th><th>**SA**</th></tr>
<tr><th><small>We believe that P1029 and P1144 are sufficiently different that they should be advanced separately.</th>
<th> 7 </th><th> 3 </th><th> 2 </th><th> 0 </th><th> 0 </th></tr>
<tr><th><small>EWGI is ok to have the spelling as an attribute with an expression argument.</th>
<th> 3 </th><th> 5 </th><th> 1 </th><th> 1 </th><th> 0 </th></tr>
<tr><th><small>EWGI thinks the author should explore P1144 as a customizable type trait.</th>
<th> 0 </th><th> 0 </th><th> 0 </th><th> 9 </th><th> 2 </th></tr>
<tr><th><small>Forward P1144 to EWG.</th>
<th> 1 </th><th> 3 </th><th> 4 </th><th> 1 </th><th> 0 </th></tr>
</table>
For polls taken September–November 2018, see [[P1144R6]].
<pre class=biblio>
{
"Abseil": {
"authors": [
"Aaron Jacobs",
"et al."
],
"title": "Abseil C++ Common Libraries",
"href": "https://github.com/abseil/abseil-cpp",
"date": "March 2023"
},
"Amadeus": {
"authors": [
"Stephane Janel"
],
"title": "AMadeus (C++) Containers",
"href": "https://github.com/AmadeusITGroup/amc",
"date": "April 2021"
},
"Announcing": {
"authors": [
"Arthur O'Dwyer"
],
"title": "Announcing \"trivially relocatable\"",
"href": "https://quuxplusone.github.io/blog/2018/07/18/announcing-trivially-relocatable/",
"date": "July 2018"
},
"Bench": {
"authors": [
"Arthur O'Dwyer"
],
"title": "Benchmark code from \"The Best Type Traits C++ Doesn't Have\"",
"href": "https://github.com/Quuxplusone/from-scratch/blob/095b246d/cppnow2018/benchmark-relocatable.cc",
"date": "April 2018"
},
"Boost.Interprocess": {
"authors": [
"Ion Gaztañaga"
],
"title": "Mapping Address Independent Pointer: offset_ptr",
"href": "https://www.boost.org/doc/libs/1_67_0/doc/html/interprocess/offset_ptr.html",
"date": "2005"
},
"BSL": {
"authors": [
"Bloomberg"
],
"title": "bslmf::IsBitwiseMoveable: bitwise moveable trait metafunction",
"href": "https://github.com/bloomberg/bde/blob/962f7aa/groups/bsl/bslmf/bslmf_isbitwisemoveable.h#L8-L48",
"date": "2013–2022"
},
"CppChat": {
"authors": [
"Howard Hinnant",
"Arthur O'Dwyer"
],
"title": "cpp.chat episode 40: It works but it's undefined behavior",
"href": "https://www.youtube.com/watch?v=8u5Qi4FgTP8",
"date": "August 2018"
},
"CppNow": {
"authors": [
"Arthur O'Dwyer"
],
"title": "Trivially Relocatable (C++Now 2019)",
"href": "https://www.youtube.com/watch?v=SGdfPextuAU",
"date": "May 2019"
},
"D50119": {
"authors": [
"Arthur O'Dwyer",
"Nicolas Lesser",
"John McCall"
],
"title": "Compiler support for P1144R0 __is_trivially_relocatable(T)",
"href": "https://reviews.llvm.org/D50119",
"date": "July 2018"
},
"D114732": {
"authors": [
"Devin Jeanpierre"
],
"title": "[clang] Mark trivial_abi types as trivially relocatable",
"href": "https://reviews.llvm.org/D114732",
"date": "November 2021"
},
"Deque": {
"authors": [
"Marc Glisse"
],
"title": "Improve relocation ... (__is_trivially_relocatable): Specialize for deque",
"href": "https://github.com/gcc-mirror/gcc/commit/a9b9381580de611126c9888c1a6c12a77d9b682e",
"date": "November 2018"
},
"FixedCapacityVector": {
"authors": [
"Arthur O'Dwyer"
],
"title": "P1144 case study: Moving a `fixed_capacity_vector`",
"href": "https://quuxplusone.github.io/blog/2019/02/22/p1144-fixed-capacity-vector/"
},
"Folly": {
"authors": [
"Facebook"
],
"title": "Folly documentation on \"Object Relocation\"",
"href": "https://github.com/facebook/folly/blob/master/folly/docs/FBVector.md#object-relocation"
},
"HPX": {
"authors": [
"Isidoros Tsaousis-Seiras"
],
"title": "Relocation Semantics in the HPX Library",
"href": "https://isidorostsa.github.io/gsoc2023/",
"date": "August 2023"
},
"InPractice": {
"authors": [
"Arthur O'Dwyer"
],
"title": "What library types are trivially relocatable in practice?",
"href": "https://quuxplusone.github.io/blog/2019/02/20/p1144-what-types-are-relocatable/",
"date": "February 2019"
},
"LWG2153": {
"authors": [
"Robert Shearer"
],
"title": "Narrowing of the non-member swap contract",
"href": "https://cplusplus.github.io/LWG/issue2153",
"date": "April 2012–October 2020"
},
"N1377": {
"authors": [
"Howard Hinnant",
"Peter Dimov",
"Dave Abrahams"
],
"title": "N1377: A Proposal to Add Move Semantics Support to the C++ Language",
"href": "http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2002/n1377.htm",
"date": "September 2002"
},
"N2754": {
"authors": [
"Rodrigo Castro Campos"
],
"title": "N2754: TriviallyDestructibleAfterMove and TriviallyReallocatable (rev 3)",
"href": "http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2008/n2754.html",
"date": "September 2008"
},
"N4158": {
"authors": [
"Pablo Halpern"
],
"title": "N4158: Destructive Move (rev 1)",
"href": "http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4158.pdf",
"date": "October 2014"
},
"P0023R0": {
"authors": [
"Denis Bider"
],
"title": "P0023R0: Relocator: Efficiently Moving Objects",
"href": "http://open-std.org/JTC1/SC22/WG21/docs/papers/2016/p0023r0.pdf",
"date": "April 2016"
},
"P0178R0": {
"authors": [
"Alisdair Meredith"
],
"title": "Allocators and swap",
"href": "https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0178r0.html",
"date": "February 2016"
},
"P0843R5": {
"authors": [
"Gonzalo Brito Gadeschi"
],
"title": "static_vector",
"href": "https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2022/p0843r5.html",