1. Introduction and motivation
C++17 knows the verbs "move," "copy," "destroy," and "swap," where "swap" is a higher-level operation
composed of several lower-level operations. To this list we propose to add the verb "relocate,"
which is a higher-level operation composed of exactly two lower-level operations.
Given an object type 
Just as the verb "swap" produces the adjective "swappable," the verb "relocate" produces the adjective
"relocatable." Any type which is both move-constructible and
destructible is relocatable. The notion can be modified by adverbs: we say that a type
is nothrow relocatable if its relocation operation is noexcept, and we say that a type
is trivially relocatable if its relocation operation is trivial (which, just like trivial move-construction
and trivial copy-construction, means "the operation is tantamount to a 
Almost all relocatable types are trivially relocatable: 
1.1. Optimizations enabled by trivial relocatability
1.1.1. Vector resize
If we have a reliable way of detecting "trivial relocatability,"
we can optimize any routine that performs the moral equivalent of 
std :: vector < R >:: resize std :: vector < R >:: reserve std :: vector < R >:: emplace_back std :: vector < R >:: push_back 
[Bench] (presented at C++Now 2018) shows a 3x speedup on 
As observed in [CppChat] (@21:55): Just as with C++11 move semantics, you can write benchmarks to show whatever speedup you like. The more complicated your types' move-constructors and destructors, the more time you save by eliminating calls to them.
1.1.2. Swap
Given a reliable way of detecting trivial relocatability,
we can optimize any routine that uses the moral equivalent of 
std :: swap std :: sort std :: vector < R >:: insert ( arguably ) 
1.1.3. More efficient small-buffer type-erasure
Given a reliable way of detecting trivial relocatability,
we can de-duplicate the code generated by small-buffer-optimized (SBO) type-erasing wrappers
such as 
1.1.4. More efficient fixed-capacity containers
Given a reliable way of detecting trivial relocatability,
we can optimize the move-constructor of 
Note: 
1.1.5. Assertions, not assumptions
Some concurrent data structures might reasonably assert the trivial relocatability of their elements, just as they sometimes assert the stronger property of trivial copyability today.
1.2. The most important benefit
Many real-world codebases already contain templates which require
trivial relocatability of their template parameters, but currently have no way to verify trivial relocatability. For example, [Folly] requires the programmer to warrant the trivial
relocatability of any type stored in a 
class Widget { std :: vector < int > lst_ ; }; folly :: fbvector < Widget > vec ; // FAILS AT COMPILE TIME for lack of warrant 
But this merely encourages the programmer to add the warrant and continue. An incorrect warrant will be discovered only at runtime, via undefined behavior. (See Allocated memory contains pointer to self and [FollyIssue889].)
class Gadget { std :: list < int > lst_ ; }; // sigh, add the warrant on autopilot template <> struct folly :: IsRelocatable < Gadget > : std :: true_type {}; folly :: fbvector < Gadget > vec ; // CRASHES AT RUNTIME due to fraudulent warrant 
If this proposal is adopted, then Folly can start using 
class Widget { std :: vector < int > lst_ ; }; static_assert ( std :: is_trivially_relocatable_v < Widget > ); // correctly SUCCEEDS class Gadget { std :: list < int > lst_ ; }; static_assert ( std :: is_trivially_relocatable_v < Gadget > ); // correctly ERRORS OUT 
The improvement in user experience for real-world codebases (such as [Folly], [EASTL], BDE, Qt, etc.) is the most important benefit to be gained by this proposal.
2. Design goals
Every C++ type already is or is not trivially relocatable. This proposal does not require any library vendor to make any library type trivially relocatable. (We assume that quality implementations will do so on their own.)
The optimizations discussed above are purely in the domain of library writers. If you’re writing
a vector, and you detect that your element type 
What C++ lacks is a standard way for library writers to detect the (existing) trivial relocatability
of a type 
There are three kinds of object types that we want to make sure are correctly detected as
trivially relocatable. These three cases are important for improving the performance of
the standard library, and for improving the correctness of programs using libraries such as [Folly]'s 
2.1. Standard library types such as std :: string 
   In order to optimize 
This could be done unilaterally by the library vendor — via a non-standard attribute (#include <string>static_assert ( is_trivially_relocatable < std :: string >:: value ); 
[[ clang :: trivially_relocatable ]] std :: is_trivially_relocatable < std :: string > That is, we can in principle solve §2.1 while confining our "magic" to the headers of the implementation itself. The programmer doesn’t have to learn anything new, so far.
2.2. Program-defined types that follow the Rule of Zero
In order to optimize the SBO 
Lambdas are not a special case in C++; they are simply class types with all their special members defaulted. Therefore, presumably we should be able to use the same solution for lambdas as for#include <string>auto lam2 = [ x = std :: string ( "hello" )]{}; static_assert ( is_trivially_relocatable < decltype ( lam2 ) >:: value ); 
Here#include <string>struct A { std :: string s ; }; static_assert ( is_trivially_relocatable < A >:: value ); 
struct  A §2.2 asks specifically that we make the 
2.3. Program-defined types with non-defaulted special members
In order to optimize 
via some standard annotation applied to class typestruct B { B ( B && ); // non-trivial ~ B (); // non-trivial }; static_assert ( is_trivially_relocatable < B >:: value ); 
B boost :: shared_ptr Note: We cannot possibly do it without annotation, because there exist
examples of types that look just like 
This use-case is the only one that requires us to design the "opt-in" syntax. In §2.1, any special syntax is hidden inside the implementation’s own headers. In §2.2, our design goal is to avoid special syntax. In §2.3, WG21 must actually design user-facing syntax.
Therefore, I believe it would be acceptable to punt on §2.3 and come back to it later. We say, "Sure, that would be nice, but there’s no syntax for it. Be glad that it works for core-language and library types. Ask again in three years." And as long as we leave the design space open, I believe we wouldn’t lose anything by delaying a solution to §2.3.
This paper does propose a standard syntax for §2.3 — an attribute — which in turn provides a simple and portable solution to §2.1 for library vendors.
3. Proposed language and library features
This paper proposes five separate additions to the C++ Standard. These additions introduce "relocate" as a well-supported C++ notion on par with "swap," and furthermore, successfully communicate trivial relocatability in each of the three use-cases above.
- 
     A new standard algorithm, uninitialized_relocate ( first , last , d_first ) < memory > 
- 
     Additional type traits, is_relocatable < T > is_nothrow_relocatable < T > < type_traits > 
- 
     A new type trait, is_trivially_relocatable < T > < type_traits > 
- 
     A new core-language rule by which a class type’s "trivial relocatability" is inherited according to the Rule of Zero. 
- 
     A new attribute, [[ trivially_relocatable ]] 
These five bullet points are severable to a certain degree. For example, if the 
Points 1 and 2 are completely severable from points 3, 4, and 5;
but we believe these algorithms should be provided for symmetry with the
other uninitialized-memory algorithms in the 
Points 3 and 4 together motivate point 5. In order to achieve the goal of §2.2 Program-defined types that follow the Rule of Zero, we must define a core-language mechanism by which we can "inherit" trivial relocatability. This is especially important for the template case.
We strongly believe thattemplate < class T > struct D { T t ; }; // class C comes in from outside, already marked, via whatever mechanism constexpr bool c = is_trivially_relocatable < C >:: value ; constexpr bool dc = is_trivially_relocatable < D < C > >:: value ; static_assert ( dc == c ); 
std :: is_trivially_relocatable < T > std :: is_trivially_destructible < T > is_trivially_relocatable is_trivially_destructible We expect that the library vendor will implement 
In point 5 we propose that the opt-in mechanism should be an attribute. The programmer
of a trivially relocatable but non-trivially destructible class 
The attribute overrides the compiler’s usual computation.struct [[ trivially_relocatable ]] C { C ( C && ); // defined elsewhere ~ C (); // defined elsewhere }; static_assert ( is_trivially_relocatable < C >:: value ); 
An example of a "conditionally" trivially relocatable class is shown in Conditionally trivial relocation.
The attribute is severable; WG21 could adopt all the rest of this proposal and
leave vendors to implement 
4. Proposed wording for C++20
The wording in this section is relative to WG21 draft N4750, that is, the current draft of the C++17 standard.
4.1. Relocation operation
Add a new section in [definitions]:
[definitions] is probably the wrong place for the core-language definition of "relocation operation"
- relocation operation
the homogeneous binary operation performed on a range by
, consisting of a move-construction immediately followed by a destruction of the source objectstd :: uninitialized_relocate 
this definition of "relocation operation" is not good
4.2. Algorithm uninitialized_relocate 
   Add a new section after [uninitialized.move]:
template < class ForwardIterator1 , class ForwardIterator2 > ForwardIterator2 uninitialized_relocate ( ForwardIterator1 first , ForwardIterator1 last , ForwardIterator2 result ); Effects: Equivalent to:
result = uninitialized_move ( first , last , result ); destroy ( first , last ); return result ; Remarks: If an exception is thrown, some objects in the range
are left in a valid but unspecified state.[ first , last ) 
Note: We are guided by [P0884R0] to make 
4.3. Algorithm uninitialized_relocate_n 
   
   template < class ForwardIterator1 , class Size , class ForwardIterator2 > pair < ForwardIterator1 , ForwardIterator2 > uninitialized_relocate_n ( ForwardIterator1 first , Size n , ForwardIterator2 result ); Effects: Equivalent to:
auto pair = uninitialized_move_n ( first , n , result ); destroy_n ( first , n ); return pair ; Remarks: If an exception is thrown, some objects in the range
are left in a valid but unspecified state.[ first , std :: next ( first , n )) 
4.4. Trivially relocatable type
Add a new section in [basic.types]:
A move-constructible, destructible object typeis a trivially relocatable type if it is:T 
a trivially copyable type, or
an array of trivially relocatable type, or
a (possibly cv-qualified) class type declared with the
attribute, or[[ trivially_relocatable ]] 
a (possibly cv-qualified) class type which:
has no user-provided move constructors,
either has at least one move constructor or has no user-provided copy constructors,
has no user-provided or deleted destructors,
either is final, or has a final destructor, or has no virtual destructors,
has no virtual base classes,
has no
ormutable members,volatile 
all of whose members are either of reference type or of trivially relocatable type, and
all of whose base classes are trivially relocatable.
[Note: For a trivially relocatable type, the relocation operation (such as the relocation operations performed by the library functions
andstd :: swap ) is tantamount to a simple copy of the underlying bytes. —end note]std :: vector :: resize [Note: It is intended that most standard library types be trivially relocatable types. —end note]
Note: We could simplify the wording by removing the words "either is final, or has a final destructor, or". However, this would lead to the compiler’s failing to identify certain (unrealistic) class types as trivially relocatable, when in fact it has enough information to infer that they are trivially relocatable in practice. This would be an inaccurate corner case in an otherwise perfectly accurate feature. I tentatively prefer to optimize for both maximum performance and absence of corner cases, over spec simplicity.
Note: There is no special treatment for volatile subobjects. Using 
Note: There is no special treatment for possibly overlapping subobjects. Using 
The relevant move constructor, copy constructor, and/or destructor must be public and unambiguous. We imply this via the words "A move-constructible, destructible object type". However, "move-constructible" and "destructible" are library concepts, not core language concepts, so maybe it is inappropriate to use them here.
We must find a rule that makes neitherstruct A { struct MA { MA ( MA & ); MA ( const MA & ) = default ; MA ( MA && ) = default ; }; mutable MA ma ; A ( const A & ) = default ; }; static_assert ( not std :: is_trivially_relocatable_v < A > ); struct B { struct MB { MB ( const volatile MB & ); MB ( const MB & ) = default ; MB ( MB && ) = default ; }; volatile MB mb ; B ( const B & ) = default ; }; static_assert ( not std :: is_trivially_relocatable_v < B > ); struct [[ trivially_relocatable ]] I { I ( I && ); }; struct J : I { J ( const J & ); J ( J && ) = default ; }; static_assert ( std :: is_trivially_relocatable_v < J > ); 
A B A ( std :: move ( a )) MA ( MA & ) B ( std :: move ( b )) MB ( const  volatile  MB & ) We would like to find a rule that makes 
4.5. [[ trivially_relocatable ]] 
   Add a new section after [dcl.attr.nouniqueattr]:
The attribute-tokenspecifies 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 functiontrivially_relocatable . It shall appear at most once in each attribute-list and no attribute-argument-clause shall be present. It may be applied to the declaration of a class. The first declaration of a type shall specify thestd :: memcpy attribute if any declaration of that type specifies thetrivially_relocatable attribute. If a type is declared with thetrivially_relocatable attribute in one translation unit and the same type is declared without thetrivially_relocatable attribute in another translation unit, the program is ill-formed, no diagnostic required.trivially_relocatable If a type
is declared with theT attribute, andtrivially_relocatable is either not move-constructible or not destructible, the program is ill-formed.T If a class type is declared with the
attribute, the implementation may replace relocation operations involving that type (such as those performed by the library functionstrivially_relocatable andstd :: swap ) with simple copies of the underlying bytes.std :: vector :: resize If a class type is declared with the
attribute, and the program relies on observable side-effects of relocation other than a copy of the underlying bytes, the behavior is undefined.trivially_relocatable 
 "If a type 
4.6. Type traits is_relocatable 
   Add new entries to Table 46 in [meta.unary.prop]:
Template Condition Preconditions template < class T > struct is_relocatable ; isis_move_constructible_v < T > trueandisis_destructible_v < T > trueT shall be a complete type, cv , or an array of unknown bound.void template < class T > struct is_nothrow_relocatable ; isis_relocatable_v < T > trueand both the indicated move-constructor and the destructor are known not to throw any exceptions.T shall be a complete type, cv , or an array of unknown bound.void template < class T > struct is_trivially_relocatable ; is a trivially relocatable type.T T shall be a complete type, cv , or an array of unknown bound.void 
4.7. Relocatable 
   Add a new section after [concept.moveconstructible]:
template < class T > concept Relocatable = MoveConstructible < T > && Destructible < T > ; Note: This concept is exactly equivalent to
.MoveConstructible < T > 
5. Alternative directions
5.1. Why not destructive move?
As discussed in EWGI at San Diego, this proposal does not give us a general user-provided "destructive move" facility.
- 
     Denis Bider’s [P0023R0] and Pablo Halpern’s [N4158] went in that direction and did not succeed. People have been chasing "destructive move" for decades; maybe it’s time to try something different. 
- 
     We get the performance benefit only when the library (e.g. std :: vector :: resize 
- 
     P1144’s approach is explicitly based on existing industry practice: [Folly], [EASTL], and [BSL] all use this exact idea in practice and it seems to work for them. Marc Glisse has been integrating the same idea into GNU libstdc++; see [Deque]. The term "relocation" is due to [EASTL] ( has_trivial_relocate IsRelocatable Q_MOVABLE_TYPE IsBitwiseMoveable 
5.2. Attribute [[ maybe_trivially_relocatable ]] 
   The Clang patch currently available on Godbolt Compiler Explorer supports not only 
P1144 talks in terms of "warranting" that a class is trivially relocatable; this can be done manually via annotation, or as a sort of "auto-warrant" done automatically by the compiler when we follow the Rule of Zero.
But another way of looking at it is that trivial relocatability is always inherited in a straightforward way, and when we use the attribute, we are "overruling" a decision made by the compiler — a decision it made for maybe several different reasons. So we can have two different levels of "overruling":
- 
     The first level, [[ clang :: maybe_trivially_relocatable ]] 
- 
     The second level, [[ clang :: trivially_relocatable ]] 
Using 
Using 
The single "Strongly Against" vote on poll 1 was due to concerns
that P1144 permits a class to warrant its own trivial relocatability, overruling the compiler’s
assumptions, not only when the compiler’s assumptions are based on the presence of special members
(e.g. 
I see cases 
// Everyone agrees that we want to allow this. struct [[ trivially_relocatable ]] A { int * p ; int i ; A () : p ( & i ), i ( 0 ) {} A ( A && rhs ) : p ( & i ), i ( rhs . i ) {} A & operator = ( A && rhs ) { i = rhs . i ; return * this ; } }; // P1144 explicitly wants to allow this; but some want to forbid it. struct [[ trivially_relocatable ]] B { boost :: interprocess :: offset_ptr < int > p ; int i ; B () : p ( & i ), i ( 0 ) {} B ( B && rhs ) : p ( & i ), i ( rhs . i ) {} B & operator = ( B && rhs ) { i = rhs . i ; return * this ; } }; // Arguably this code has poor style. // P1144 explicitly wants to allow this; but some want to forbid it. struct [[ trivially_relocatable ]] C { boost :: shared_ptr < int > p ; C ( C && ) = default ; C & operator = ( C && ) = default ; }; // This code is buggy. // P1144 allows you to shoot yourself in the foot like this. struct [[ trivially_relocatable ]] D { std :: list < int > lst ; D ( D && ) = default ; D & operator = ( D && ) = default ; }; 
I believe a major problem with 
template < class T > struct optional_destruct_base { bool engaged ; union { char dummy ; T t ; }; ~ optional_destruct_base () { if ( engaged ) t . ~ T (); } }; template < class T > struct optional_move_base : optional_destruct_base < T > { ... }; template < class T > class optional : optional_move_base < T > { ... }; 
In a P1144 
In a 
Lastly, the concern over 
The proposed attribute is a simple, sharp knife. It cuts what you point it at; point it carefully. 
5.3. Attribute [[ trivially_relocatable ( bool )]] 
   It has been suggested by numerous reviewers that 
See Conditionally trivial relocation for an example of how this would be used.
There is no technical obstacle to adding an arbitrary C++ expression as the parameter to
an attribute. The grammar for balancing 
I’m amenable to this idea. The major downside I see to it is that it could lead to an arbitrarily complicated C++ expression appearing in an awkward position. But this is not necessarily worse, and perhaps better, than having to do the metaprogramming tricks shown in Conditionally trivial relocation.
5.4. relocate std :: list 
   (See "Trivially Relocatable versus Destructive Movable" (2018-09-28) for a detailed analysis of this material.)
Pablo Halpern’s [N4158] proposed a completely user-space mechanism: an ADL customization point
named 
That middle ground would be useful for types such as MSVC’s 
But if there were a way for MSVC’s 
However, since the calling of 
template < class T > struct CustomList : std :: list < T > { using std :: list < T >:: list ; CustomList ( CustomList && rhs ) noexcept : list ( rhs ) {} }; 
The ADL-customization-point path seems to have a very high cost-to-benefit ratio. I am satisfied with P1144’s ignoring it.
5.5. Unintuitive is_nothrow_relocatable 
   Consider a type such as
struct [[ trivially_relocatable ]] Widget { int i ; Widget ( Widget && ) : i ( rhs . i ) {} }; static_assert ( not std :: is_nothrow_move_constructible_v < Widget > ); static_assert ( not std :: is_nothrow_relocatable_v < Widget > ); static_assert ( not std :: is_trivially_relocatable_v < Widget > ); 
Since 
This is a real-world concern because GNU libstdc++'s 
However, I believe that it would be incorrect and unsafe for the library to claim that 
I believe P1144’s proposed behavior is the best behavior. However, another plausible behavior
would be to simply eliminate the 
6. Acknowledgements
Thanks to Elias Kosunen, Niall Douglas, and John Bandela for their feedback on early drafts of this paper.
Many thanks to Matt Godbolt for allowing me to install the prototype Clang implementation on Compiler Explorer (godbolt.org). See also [Announcing].
Thanks to Nicolas Lesser for his relentless feedback on drafts of P1144R0, and for his helpful review comments on the Clang implementation [D50119].
Thanks to Howard Hinnant for appearing with me on [CppChat], and to Jon Kalb and Phil Nash for hosting us.
Thanks to Pablo Halpern for [N4158], to which this paper bears a striking and coincidental resemblance —
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 [P1029R0] (treating relocatability as an aspect of move-construction in isolation, rather than an aspect of the class type as a whole).
Thanks to John McCall for his thought-provoking review comments on the Clang implementation [D50119].
Thanks to Marc Glisse for his work integrating a "trivially relocatable" trait into GNU libstdc++ and for answering my questions on GCC bug 87106.
Appendix A: Straw polls
Polls taken of the Internet between 2018-11-12 and 2018-11-21
| SF | F | N | A | SA | |
|---|---|---|---|---|---|
| We approve of the general idea that user-defined classes should be able to warrant their own trivial relocatability via a standard mechanism. | 6 | 1 | 0 | 0 | 1 | 
| We approve of the general idea that user-defined classes which follow the Rule of Zero should inherit the trivial relocatability of their bases and members. | 7 | 1 | 0 | 0 | 0 | 
| Nobody should be able to warrant the trivial relocatability of except foritself (i.e., we do not want to see a customization point analogous to). | 4 | 2 | 2 | 0 | 0 | 
| A class should be able to warrant its own trivial relocatability via the attribute , as proposed in this paper (P1144R0). | 3 | 0 | 3 | 1 | 0 | 
| A class should be able to warrant its own trivial relocatability via some attribute, but not necessarily under that exact name. | 2 | 0 | 4 | 1 | 0 | 
| A class should be able to warrant its own trivial relocatability as proposed in this paper (P1144R0), but via a contextual keyword rather than an attribute. | 0 | 2 | 3 | 3 | 0 | 
| If a trait with the semantics of is added to theheader, the programmer should be permitted to specialize it for program-defined types (i.e., we want to see that trait itself become a customization point analogous to). | 0 | 1 | 0 | 1 | 5 | 
| Trivial relocatability should be assumed by default. Classes such as those in Appendix C should indicate their non-trivial relocatability via an opt-in mechanism. | 0 | 0 | 0 | 3 | 5 | 
| To simplify Conditionally trivial relocation, if an attribute with the semantics of is added, it should take a boolean argument. | 1 | 1 | 3 | 2 | 0 | 
| The algorithm should be added to theheader,
as proposed in this paper (P1144R0). | 0 | 4 | 1 | 1 | 0 | 
| The type trait (and itsversion) should be added to theheader, as proposed in this paper (P1144R0). | 0 | 2 | 3 | 0 | 1 | 
| If is added, then we should also add(and itsversion), as proposed in this paper (P1144R0). | 1 | 4 | 2 | 0 | 0 | 
| The type trait (and itsversion) should be added to theheader, under that exact name, as proposed in this paper (P1144R0). | 3 | 3 | 1 | 0 | 0 | 
| We approve of a trait with the semantics of , but not necessarily under that exact name. (For example,.) | 3 | 3 | 0 | 1 | 0 | 
| If is added, under that exact name, then the type trait(and itsversion) should also be added to theheader. | 0 | 3 | 3 | 0 | 0 | 
The "Strongly Against" vote on poll 1 was due to concerns that P1144 permits a class to warrant its own trivial relocatability, overruling the compiler’s assumptions, not only when the compiler’s assumptions are based on the presence of special members, but also when the compiler’s assumptions are based partly or wholly on the non-triviality of member or base subobjects. See further discussion under §5.2 Attribute [[maybe_trivially_relocatable]].
The "Against" vote on poll 10, 
The "Strongly Against" vote on poll 11, 
Poll taken of EWGI at San Diego on 2018-11-07
| SF | F | N | A | SA | |
|---|---|---|---|---|---|
| Should we commit additional committee time to solving the problem P1144R0 is trying to solve, knowing it will leave less time to other work? | 8 | 3 | 0 | 0 | 0 | 
Polls taken of SG14 at CppCon on 2018-09-26
| SF | F | N | A | SA | |
|---|---|---|---|---|---|
| The type trait (and itsversion) should be added to theheader, under that exact name, as proposed in this paper. | 1 | 20 | 7 | 1 | 0 | 
| We approve of a trait with the semantics of , but not necessarily under that exact name. (For example,.) | 15 | 12 | 1 | 0 | 0 | 
| We approve of the general idea that user-defined classes should be able to warrant their own trivial relocatability. | 25 | 5 | 2 | 0 | 0 | 
Appendix B: Sample code
Reference implementation of std :: uninitialized_relocate 
   
    template < class ForwardIterator1 , class ForwardIterator2 > ForwardIterator2 uninitialized_relocate ( ForwardIterator1 first , ForwardIterator1 last , ForwardIterator2 result ) { using T = typename iterator_traits < ForwardIterator2 >:: value_type ; using U = decltype ( std :: move ( * first )); constexpr bool memcpyable = ( std :: is_same_v < T , std :: remove_ref_t < U >> && std :: is_trivially_relocatable_v < T > ); constexpr bool both_contiguous = ( std :: is_pointer_v < ForwardIterator1 > && std :: is_pointer_v < ForwardIterator2 > ); constexpr bool nothrow_relocatable = std :: is_nothrow_constructible_v < T , U > ; if constexpr ( memcpyable && both_contiguous ) { std :: size_t nbytes = ( char * ) last - ( char * ) first ; if ( nbytes != 0 ) { std :: memmove ( std :: addressof ( * result ), std :: addressof ( * first ), nbytes ); result += ( last - first ); } } else if constexpr ( nothrow_relocatable ) { for (; first != last ; ( void ) ++ result , ++ first ) { :: new ( static_cast < void *> ( std :: addressof ( * result ))) T ( std :: move ( * first )); std :: destroy_at ( std :: addressof ( * first )); } } else { result = std :: uninitialized_move ( first , last , result ); std :: destroy ( first , last ); } return result ; } 
Conditionally trivial relocation
We expect, but do not require, that 
The following abbreviated implementation shows how to achieve an 
The primitives of move-construction and destruction are provided by four specializations
of 
template < class T > class optional : optional_relocate_base < T > { using optional_relocate_base < T >:: optional_relocate_base ; }; template < class T , bool R = is_trivially_relocatable_v < T >> class optional_relocate_base : optional_base < T > { using optional_base < T >:: optional_base ; }; template < class T > class [[ trivially_relocatable ]] optional_relocate_base < T , true> : optional_base < T > { using optional_base < T >:: optional_base ; }; template < class T , bool D = is_trivially_destructible_v < T > , bool M = is_trivially_move_constructible_v < T >> class optional_base { // NOT SHOWN }; 
If we adopt the boolean-parameter syntax proposed by §5.3 Attribute [[trivially_relocatable(bool)]], then
we could eliminate the helper class 
template < class T > class [[ trivially_relocatable ( is_trivially_relocatable_v < T > )]] optional : optional_base < T > { using optional_base < T >:: optional_base ; }; template < class T , bool D = is_trivially_destructible_v < T > , bool M = is_trivially_move_constructible_v < T >> class optional_base { // NOT SHOWN }; 
Appendix C: Examples of non-trivially relocatable class types
Class contains pointer to self
This fictional 
However, different mechanisms for small-buffer optimization exist. libc++'s std::any also achieves small-buffer optimization on a 24-byte buffer, without (necessarily) sacrificing trivial relocatability.
struct short_string { char * data_ = buffer_ ; size_t size_ = 0 ; char buffer_ [ 8 ] = {}; const char * data () const { return data_ ; } short_string () = default ; short_string ( const char * s ) : size_ ( strlen ( s )) { if ( size_ < sizeof buffer_ ) strcpy ( buffer_ , s ); else data_ = strdup ( s ); } short_string ( short_string && s ) { memcpy ( this , & s , sizeof ( * this )); if ( s . data_ == s . buffer_ ) data_ = buffer_ ; else s . data_ = nullptr ; } ~ short_string () { if ( data_ != buffer_ ) free ( data_ ); } }; 
Allocated memory contains pointer to self
Traditional implementations of 
struct node { node * prev_ = nullptr ; node * next_ = nullptr ; }; struct list { node n_ ; iterator begin () { return iterator ( n_ . next_ ); } iterator end () { return iterator ( & n_ ); } list ( list && l ) { if ( l . n_ . next_ ) l . n_ . next_ -> prev_ = & n_ ; // fixup if ( l . n_ . prev_ ) l . n_ . prev_ -> next_ = & n_ ; // fixup n_ = l . n_ ; l . n_ = node {}; } // ... }; 
Class invariant depends on this 
   The 
struct offset_ptr { uintptr_t value_ ; uintptr_t here () const { return uintptr_t ( this ); } uintptr_t distance_to ( void * p ) const { return uintptr_t ( p ) - here (); } void * get () const { return ( void * )( here () + value_ ); } offset_ptr () : value_ ( distance_to ( nullptr )) {} offset_ptr ( void * p ) : value_ ( distance_to ( p )) {} offset_ptr ( const offset_ptr & rhs ) : value_ ( distance_to ( rhs . get ())) {} offset_ptr & operator = ( const offset_ptr & rhs ) { value_ = distance_to ( rhs . get ()); return * this ; } ~ offset_ptr () = default ; }; 
Program invariant depends on this 
   In the following snippet, 
std :: set < void *> registry ; struct registered_object { registered_object () { registry . insert ( this ); } registered_object ( registered_object && ) = default ; registered_object ( const registered_object & ) = default ; registered_object & operator = ( registered_object && ) = default ; registered_object & operator = ( const registered_object & ) = default ; ~ registered_object () { registry . erase ( this ); } }; struct Widget : registered_object {}; 
Appendix D: Implementation
A prototype Clang/libc++ implementation is at
- 
     godbolt.org, under the name "x86-64 clang (experimental P1144)" 
Furthermore, as of November 2018, libstdc++ trunk will perform the