C++ Logo

std-proposals

Advanced search

Re: [std-proposals] Replace an object -- but retain old object if new object fails to construct

From: Thiago Macieira <thiago_at_[hidden]>
Date: Wed, 22 Oct 2025 10:40:41 -0700
On Wednesday, 22 October 2025 10:15:01 Pacific Daylight Time Frederick
Virchanza Gotham via Std-Proposals wrote:
> So I understand what relocation is . . . and I understand that some classes
> will have their methods malfunction if an object is moved to a different
> address.

Which is a sufficient condition for what you want.

Not a necessary condition, I agree. But how often do we need your proposed
feature for non-relocatable objects?

We can expand the functionality once the need arises, with the help of
reflection because then we can query a type's attributes.

> Essentially in this thread, I'm talking about constructing a new object and
> waiting until we're sure it has been fully constructed before invoking the
> destructor of the old object. My sneaky strategy of swapping raw bytes
> around will work fine so long as, during the construction and destruction,
> no object of type T tries to access another object of type T. This is
> pretty reasonable as less than 1% of classes access some sort of global
> directory of objects or have some sort of linked list to other existent
> objects.

The issue is the sneaky strategy. If you propose the feature without the
sneaky strategy, then there's no problem: a temporary is created on the stack
by moving from the existing element, then a new one is constructed in the
storage area (instead of copy- or move-assigned) and, if that succeeds, then
the old one is destroyed.

If the type is relocatable, then the function can do this operation in a more
optimised way. Whether the standard should *require* it do so is a different
story.

> I don't see how my byte-swapping strategy has anything to do with
> relocatability. Let me use a class as an example:

Byte-swapping *IS* relocation. That's the whole point of the feature.

> std::string
>
> This class is not trivially relocatable because the short-string
> optimisation maintains a pointer into the object. A special algorithm is
> needed to relocate an std::string (which I show in my above linked PDF
> paper near the last page). But even though an std::string is not trivially
> relocatable, there's absolutely no harm in swapping its bytes around to do
> a clever construct and destruct trick.

Indeed. But I don't think that's a big deal. Moving the bytes around twice is
potentially a *worse* result for std::string than simply moving it out of the
way and later destroying it.

A libstdc++ std::string is 32 bytes on 64-bit platforms. In your way:
1) copy 32 bytes from storage to temporary A
2) move-construct new object (copy 32 bytes from incoming to storage)
3) copy 32 bytes from storage to temporary B
4) copy 32 bytes from temporary A back to storage
5) destroy old string
6) copy 32 byes from temporary B back to storage

If temporary A and temporary B in your example are 32-byte YMM registers so
that no stack memory is actually used, the first two "copy" are "load" and the
latter two are "store". If either the move construction (step 2) or the
destruction (step 5) call out-of-line functions, then the YMM registers aren't
available and stack space must be used.

A regular solution would be:
1) move-construct temporary string (copy 32 bytes from storage to tmp)
2) move-construct new object (copy 32 bytes from incoming to storage)
3) destroy old string in tmp

This implementation loads 2x32 bytes and stores 2x32 bytes. Therefore, it's
*as optimal* as your solution would be or better than it, if the compilers did
spill to the stack.

So I don't see why one should try what you're suggesting for a non-relocatable
type.

> The question is: Is it possible that the 'emplace_or_retain' function could
> cause malfunctions with some classes? My answer is Yes, it can, if the
> class in its constructor or destructor accesses other objects of the same
> class. But I really don't understand where relocatability comes into it. I
> don't get it.

Because relocatability guarantees the constructor or destructor won't.

-- 
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
  Principal Engineer - Intel Data Center Group

Received on 2025-10-22 17:40:50