Date: Tue, 21 Oct 2025 10:09:01 -0700
On Tuesday, 21 October 2025 09:03:28 Pacific Daylight Time Frederick Virchanza
Gotham via Std-Proposals wrote:
> (Step 1) Copy the bytes of the current object into a temporary buffer
> on the stack
> (Step 2) Construct the new object at the original location of the old
> object (i.e. overwrite the old object)
> (Step 3) If constructor throws an exception, move the old object's
> bytes back from the temporary buffer (i.e. restore the old object)
> (Step 4) Otherwise, if construction succeeds, swap the two buffers,
> call the destructor to destroy the old object, then swap the two
> buffers again
What if the constructor in step 2 attempts to use the object that was there?
It's perfectly possible for constructors to access a global list of live
objects. Likewise for the destruction in step 4 could access the list of live
objects.
This cannot be done in the generic case. I suggest this feature require that
the class type be relocatable, otherwise it shouldn't be available.
> Now see here's the thing . . . I'm probably more of a firmware
> engineer than a software engineer, and so I have a little difficulty
> maintaining respect for the "object model" since I deal so much with
> copper and voltages and CPU registers, but I can at least concede that
> my above code absolutely decimates the object model in the most
> horrendous and unspeakable manner. Also I'm pretty sure I'm not
> allowed to 'memcpy' a class like 'std::mutex' either.
Only memcpying it away and back again is fine, because under the as-if rule one
can't tell you did that. The problem is that you did something to its storage
space while the object was away and that violates as-if.
And a likely type to know of existing objects are mutexes, because for almost
every OS out there they must make a system call to initialise OS-specific
objects. If you doubt me, look at FreeBSD's implementation of pthread_mutex:
https://github.com/freebsd/wireless/blob/main/lib/libthr/thread/thr_mutex.c
https://github.com/freebsd/wireless/blob/main/lib/libthr/thread/thr_private.h
It even has a linked list!
[Fortunately, on the majority of OSes, there's a way to constexprly initialise
a std::mutex object, delaying the full initialisation to the first lock() call.
libc++ appears to require that mode, but libstdc++ supports non-constexpr
inits and *uses* that for Windows, calling InitializeCriticalSection()].
> So anyway, to get around the whole object model boggle and memcpy's
> class bytes, perhaps could the standard library be given a new
> function called something like "emplace_or_retain", and so then
> compiler vendors could take my above code and put it in their header
> files and then put some fine print with it saying "The compiler
> maintains the sanctity of the C++ object model when compiling this
> code".
As I said above, I think only for relocatable objects. Which std::mutex won't
be.
Gotham via Std-Proposals wrote:
> (Step 1) Copy the bytes of the current object into a temporary buffer
> on the stack
> (Step 2) Construct the new object at the original location of the old
> object (i.e. overwrite the old object)
> (Step 3) If constructor throws an exception, move the old object's
> bytes back from the temporary buffer (i.e. restore the old object)
> (Step 4) Otherwise, if construction succeeds, swap the two buffers,
> call the destructor to destroy the old object, then swap the two
> buffers again
What if the constructor in step 2 attempts to use the object that was there?
It's perfectly possible for constructors to access a global list of live
objects. Likewise for the destruction in step 4 could access the list of live
objects.
This cannot be done in the generic case. I suggest this feature require that
the class type be relocatable, otherwise it shouldn't be available.
> Now see here's the thing . . . I'm probably more of a firmware
> engineer than a software engineer, and so I have a little difficulty
> maintaining respect for the "object model" since I deal so much with
> copper and voltages and CPU registers, but I can at least concede that
> my above code absolutely decimates the object model in the most
> horrendous and unspeakable manner. Also I'm pretty sure I'm not
> allowed to 'memcpy' a class like 'std::mutex' either.
Only memcpying it away and back again is fine, because under the as-if rule one
can't tell you did that. The problem is that you did something to its storage
space while the object was away and that violates as-if.
And a likely type to know of existing objects are mutexes, because for almost
every OS out there they must make a system call to initialise OS-specific
objects. If you doubt me, look at FreeBSD's implementation of pthread_mutex:
https://github.com/freebsd/wireless/blob/main/lib/libthr/thread/thr_mutex.c
https://github.com/freebsd/wireless/blob/main/lib/libthr/thread/thr_private.h
It even has a linked list!
[Fortunately, on the majority of OSes, there's a way to constexprly initialise
a std::mutex object, delaying the full initialisation to the first lock() call.
libc++ appears to require that mode, but libstdc++ supports non-constexpr
inits and *uses* that for Windows, calling InitializeCriticalSection()].
> So anyway, to get around the whole object model boggle and memcpy's
> class bytes, perhaps could the standard library be given a new
> function called something like "emplace_or_retain", and so then
> compiler vendors could take my above code and put it in their header
> files and then put some fine print with it saying "The compiler
> maintains the sanctity of the C++ object model when compiling this
> code".
As I said above, I think only for relocatable objects. Which std::mutex won't
be.
-- Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org Principal Engineer - Intel Data Center Group
Received on 2025-10-21 17:09:09
