Cheaply relocatable, but not trivially relocatable
On GCC bug 87106, Marc Glisse raises the following interesting example:
I think it might be useful to be able to specify how to relocate an object that is not trivially relocatable. Relocating a
pair<A,B>whereAis trivially relocatable andBis not can still benefit from doing piecewise relocations so it avoidsA’s super-costly move constructor.
Expressed in P1144R0 syntax:
struct [[trivially_relocatable]] A {
A(A&&);
~A();
};
static_assert(is_trivially_relocatable_v<A>);
struct B {
B(B&&);
~B();
};
static_assert(not is_trivially_relocatable_v<B>);
using C = std::pair<A, B>;
static_assert(not is_trivially_relocatable_v<C>);
Ideally, C’s “relocate” operation would use memcpy for the A component
but then dispatch to B(B&&) and ~B() for the B component. So it’d call
memcpy, B(B&&), and ~B().
Since P1144 does not propose any first-class “relocate operation,” there’s no
way for the designer of C (that is, the designer of std::pair) to indicate
that this is how “relocation” ought to work for C. And C is definitely not
trivially relocatable, because of the B component. So the result is that
relocating a C falls back to the only fallback we know: calling C’s
move constructor and destructor.
So it ultimately calls A(A&&), B(B&&), ~A(), and ~B().
So this is an example of a situation where a first-class “relocate” operation — such as the one proposed by Denis Bider in P0023 “Relocator: Efficiently moving objects” (April 2016) — would produce more benefit than P1144’s focus on trivially relocatable objects.
TL;DR:
using CheaplyButNotTriviallyRelocatable =
tuple<string, string, string, string, list<int>>;
