C++ Logo

std-proposals

Advanced search

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

From: Gašper Ažman <gasper.azman_at_[hidden]>
Date: Tue, 1 Feb 2022 10:04:19 +0000
Hi Sebastien,

you sure made a pretty long write-up! What I'm missing on the first
skim-through is a thorough review of the currently published papers in the
space and answers to the previously surfaced objections.

Some of the papers in this space:
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p1144r5.html
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4158.pdf
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p1029r3.pdf
http://open-std.org/JTC1/SC22/WG21/docs/papers/2016/p0023r0.pdf

I also couldn't find any way that your proposal handles maybe-destroy
references. For instance, how do you handle

bool maybe_destroy(T& x) {
    if (rand() % 2) { T(static_cast<T~>(x)); return true; }
    return false;
}

The compiler will still emit the destructor call for x in the caller of
maybe_destroy - there's nothing in the interface that communicates whether
an object has been destroyed or not, *to the compiler*. Being able to
handle this case has been the major stumbling block for pretty much every
proposal in this space.

G

On Tue, Feb 1, 2022 at 9:26 AM Sébastien Bini via Std-Proposals <
std-proposals_at_[hidden]> wrote:

> Hello everyone,
>
> I've worked on a proposal in the last months to introduce relocation (a
> destructive move) in C++. I wrote the proposal (you will find it enclosed
> with this email) but it's quite large so I'll write a small overview here.
>
> Relocation allows to "move" one object into another one. It is similar to
> move constructors, except that relocation guarantees that moved objects are
> destructed right after and cannot be reused.
>
> This proposal is motivated by:
> - the confusing and often not properly implemented "moved-from" state,
> introduced by move constructor.
> - relocation is simpler to implement than move semantics as the relocated
> object can be left in a dirty invalid state.
> - const variables cannot be moved with C++ move semantics. But they can
> "relocated" with this proposal.
>
> This introduces three main additions to the language:
>
> 1. Relocation reference
>
> A new type of reference, called "relocation reference". A relocation
> reference on T is denoted by T~. This reference is mainly introduced
> because of the new constructor.
>
> 2. Relocation constructor
>
> We introduce a new constructor, the relocation constructor:
> class T {
> T(T~ other) noexcept;
> };
>
> This constructor has a new feature no other C++ constructor has: *it acts
> as a destructor with regards to its parameter* ("other" in the code
> sample). Hence when this constructor is called, a new instance is built as
> always, but the instance it was built from is destructed. This means that
> the destructor of the moved instance must not be called (otherwise the
> instance would be destructed twice).
>
> This constructor is usually quite straightforward to implement, you need
> simply to copy all data-members from other into the new instance.
>
> For instance, implementing the relocation constructor for std::unique_ptr
> is simple. You simply need to copy the internal pointer to the new
> instance. *The moved instance can be left untouched, and the memory it
> still owns won't be deleted as the moved instance destructor will not be
> called*.
> In fact there is so little to do that the default implementation does the
> job:
> unique_ptr(unique_ptr~) noexcept = default;
>
> 3. The reloc operator
>
> Lastly, we introduce a new unary operator: reloc. It will usually be used
> like this: auto y = reloc x;
> This relocates x into y, leaving x in a destructed state.
> This new operator (a) handles the construction of the new instance (will
> use the relocation constructor, the move constructor or the copy
> constructor, picked in that order), (b) ensures the destruction of the
> relocated instance and (c) prevents any further use in the code of the
> relocated instance.
>
> Consider the following scenario:
> const T x;
> auto y = reloc x;
> // std::cout << x << std::endl;
>
> The second line builds y from x:
> - Case 1: the type of x provides a relocation constructor: The relocation
> constructor is called. At the end of the expression x is considered
> destructed because of the relocation constructor. The destructor of x will
> not be called when its end of scope is reached.
> - Case 2: the type of x does not provide a relocation constructor, but a
> move or copy constructor: The move constructor is called if it exists (if
> not the copy constructor is called) to construct y from x. reloc must
> ensure the destruction of x, so the destructor of x is called at the end of
> the evaluation of the second line.
>
> The third line attempts to reuse a variable that was relocated.
> Uncommenting this line will raise a compile error. reloc forbids further
> mention of a name that resolves to a relocated object.
>
> This is it, thank you for reading :)
>
> Best regards,
> Sébastien Bini
> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>

Received on 2022-02-01 10:04:31