C++ Logo

std-proposals

Advanced search

Re: [std-proposals] Relocation in C++

From: Arthur O'Dwyer <arthur.j.odwyer_at_[hidden]>
Date: Mon, 30 May 2022 12:23:34 -0400
On Mon, May 30, 2022 at 11:37 AM Edward Catmur via Std-Proposals <
std-proposals_at_[hidden]> wrote:

> On Mon, 30 May 2022 at 09:26, Maciej Cencora via Std-Proposals <
> std-proposals_at_[hidden]> wrote:
>
>> Can't we base relocation on move+destroy only? (or just memcpy + end
>> of scope in case of trivially relocatable types).
>>
>> I.e.:
>> Obj a;
>> auto b = reloc a;
>>
>> At 'reloc a' line, we either:
>> 1) construct 'b' by invoking move constructor from 'a', invoke
>> destructor for 'a', remove 'a' from scope
>> 2) construct 'b' by memcpy-ing 'a', do not invoke 'a' destructor,
>> remove ab' from scope
>>
>
> We expect there to exist types that are immovable and [non-trivially]
> relocatable.
>

FWIW, I (in P1144) consider that an oxymoron. A type that is
immobile/immovable cannot be relocatable, because it's not movable.
Immobility is for types that cannot be moved from place to place — like
`std::mutex`, for example. Typically they cannot be moved because *if you
moved them then bad things would happen*.
Similarly, if you "relocated" a `std::mutex`, *bad things would happen*.
You can't have a mutex suddenly change memory addresses and expect the rest
of the program to just be cool with that.

The right answer to Maciej's question is: Because you expect there to exist
types that are *efficiently relocatable but not trivially relocatable.*
One real-world example is
    struct S {
        std::any a; // non-trivially relocatable
        std::list<int> b; // MSVC: trivially relocatable, inefficiently
movable
    };
To move-construct an `S`, you need to move the any (using its move-ctor)
and then move the list (using its move-ctor, which allocates memory because
MSVC uses a sentinel-node implementation).
But to relocate an `S`, you merely need to move-and-destroy the any (still
using its move-ctor, presumably) and then relocate the list (using its
relocation operation, which is tantamount to memcpy, and does not allocate).
Move-constructing an `S` allocates, and is non-noexcept.
Relocating an `S` doesn't need to allocate, and can be noexcept.
*However*, `S` is not trivially relocatable.

So, it's tempting to look for some syntax to express a relocation operation
that is different from move+destroy and yet also different from memcpy.
That's what Sébastien is doing here (and also Pablo in N4158, and Denis in
P0023).

Relevant:
https://quuxplusone.github.io/blog/2019/02/20/p1144-what-types-are-relocatable/

–Arthur

Received on 2022-05-30 16:23:47