C++ Logo

std-proposals

Advanced search

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

From: Sébastien Bini <sebastien.bini_at_[hidden]>
Date: Wed, 1 Jun 2022 11:29:32 +0200
> template<class T> requires is_noexcept_relocatable_v<T>
> constexpr void swap(T& lhs, T& rhs) {
> union { char c; T t; } u = { .c = '\0' };
> relocate_at(&lhs, &u.t);
> relocate_at(&rhs, &lhs);
> relocate_at(&u.t, &rhs);
> u.c = '\0';
> }
>
> And I'm not 100% sure that this is constexpr (&u.t is doing a lot of
work). So I'd prefer the version using std::relocate, std::relocate_at,
operator reloc. This is a good demonstration of why all 3 of std::relocate,
std::relocate_at, operator reloc are necessary.

That seems to be only constexpr given that T is trivially destructible /
constructible (at least from what clang 13 is telling me).

If the sole point for having std::relocate is for std::swap, why not have a
magic compiler generated constexpr std::swap that uses relocation? I fear
that having operator reloc and std::relocate will be confusing.

> "reloc-assign" is just assignment by value: operator=(T). See my email
just now.

That should do.

> I don't see the need for push_back to take a tag parameter at all; we can
just add push_back by value: void push_back(T value);. Possibly the
overload resolution rules will need updating, or the existing overloads
(T&& / T const&) could be removed.

How would you update those rules?

> While the copy-and-swap (in this case, reloc-and-swap) idiom works fine
for this assignment operator, for gsl::not_null a memberwise implementation
would also work, indicating that this assignment operator should be a
defaultable special member function:
>
> not_null& operator=(not_null) = default;

That should work. Although I believe that assignment relocation could
happen in terms of destruction + relocation, at least for types that
support operator reloc().

> In turn, this indicates that the spelling for the relocation operator
should simply be T(T) - that is, it should have the syntax of a
constructor. Since a by-value constructor is currently invalid, this is
free syntax.

I am not thrilled by this :/

   - T(T) does not convey the intent like "operator reloc(T&&)" does;
   - Users may find it confusing to have a constructor overload that takes
   parameters by value;
   - T(T) would mean that the destructor of the parameter is called when
   the function exits, which is not the case;
   - That syntax would only imply that a copy of the object is performed
   and that copy is placed in the constructor parameter. While this is not
   what happens: `reloc obj` will simply pass 'obj' as parameter, and we lie
   when we say it's a pr-value. Unlike assignment-relocation (T&
   operator=(T)), where the parameter is an actual pr-value, returned by
   reloc. Unless I am missing something?
   - This syntax would allow code like: T a; T b{a}; What happens then? Is
   the copy constructor called or the relocation constructor? If the latter,
   then `a` will be double-freed. If the former, then how does overload
   resolution figure this one out?


On Wed, Jun 1, 2022 at 1:19 AM Edward Catmur <ecatmur_at_[hidden]> wrote:

> On Tue, 31 May 2022 at 10:24, Edward Catmur <ecatmur_at_[hidden]>
> wrote:
>
>> "reloc-assign" is just assignment by value: operator=(T). See my email
>> just now.
>>
>
> While the copy-and-swap (in this case, reloc-and-swap) idiom works fine
> for this assignment operator, for gsl::not_null a memberwise implementation
> would also work, indicating that this assignment operator should be a
> defaultable special member function:
>
> not_null& operator=(not_null) = default;
>
> In turn, this indicates that the spelling for the relocation operator
> should simply be T(T) - that is, it should have the syntax of a
> constructor. Since a by-value constructor is currently invalid, this is
> free syntax.
>

Received on 2022-06-01 09:29:44