On Wed, Oct 22, 2025 at 1:40 PM Thiago Macieira via Std-Proposals <std-proposals@lists.isocpp.org> 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