Date: Thu, 23 Oct 2025 06:56:16 +0200
The initial example was motivated by std::mutex which neither copyable nor movable. The current discussion of relocatability/trivial relocatability is not helping in this scenario. I agree that on most real world computers this strategy would most likely work. While the object is temporarily placed in new memory, its lifetime has been suspended and no functions can be called on it. Currently, C++ does not have a concept of suspended lifetimes. This means this can only be a proposal if we heavily change the wording of the C++ standard to include this new concept. If no one is willing to do this, we can stop the discussion right now.
On Oct 22, 2025, at 8:14 PM, Arthur O'Dwyer via Std-Proposals <std-proposals_at_[hidden]> wrote:
--On Wed, Oct 22, 2025 at 1:40 PM Thiago Macieira via Std-Proposals <std-proposals_at_[hidden]> wrote: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.Part of the confusion here, I think, is because Thiago said (and continues, sometimes, to say) "relocatable" when he meant specifically "trivially relocatable."You can do the replacement operation like this:template<class T, class... Args>void replace(T *where, Args&&... args) {static_assert(std::is_nothrow_destructible_v<T>);if (std::is_nothrow_constructible_v<T, Args...>) {std::destroy_at(where);std::construct_at(where, std::forward<Args>(args)...);} else if (std::is_nothrow_relocatable_v<T, Args...>) {alignas(T) char elsewhere[sizeof(T)];std::relocate_at(where, (T*)elsewhere);try {std::construct_at(where, std::forward<Args>(args)...);} catch (...) {std::relocate_at((T*)elsewhere, where);throw;}std::destroy_at((T*)elsewhere);} else {// We can't really do it in a nice way, but we can use FVG's approach:char elsewhere[sizeof(T)];std::memcpy(elsewhere, where, sizeof(T));try {std::construct_at(where, std::forward<Args>(args)...);} catch (...) {std::memcpy(where, elsewhere, sizeof(T));throw;}char yetagain[sizeof(T)];std::memcpy(yetagain, where, sizeof(T));std::memcpy(where, elsewhere, sizeof(T));std::destroy_at(where);std::memcpy(where, yetagain, sizeof(T));}}`is_nothrow_relocatable` is a strictly weaker condition than `is_trivially_relocatable`: all trivially relocatable types are nothrow relocatable.If relocation can throw, then you have to use the third-and-ugliest approach above, which relies on the idea that you can memcpy the representation out of an object, then memcpy it back (to the exact same address), and continue to use the object. This is true on all platforms I'm aware of, but technically not guaranteed by the Standard.If the object is actually (nothrow) relocatable, then you don't have to memcpy it back to the exact same address in order to destroy it safely. You can simply destroy the relocated copy (at its new address) instead of the original. This is the second-and-relatively-prettier approach above.> 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.No, byte-swapping is trivial relocation.(At least, it is in a sane world, and hopefully the large number of NB comments on trivial relocation will get us to that sane world in the end. The C++26 CD is not sane.)–Arthur
Std-Proposals mailing list
Std-Proposals_at_[hidden]
https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
Received on 2025-10-23 04:56:34
