Reputation: 2734
This is a follow up of Bitwise swapping the internal representation of two simple objects, even if they are not of a trivially copyable type.
I merely simplify a bit OP snippet and make the considered type trivially copyable:
#include<cstddef>
#include <cstring>
#include <type_traits>
struct SimpleClass {};
int main() {
static_assert(std::is_trivially_copyable_v<SimpleClass>);
SimpleClass s1;
SimpleClass s2;
constexpr size_t SimpleClass_SIZE = sizeof(SimpleClass);
alignas(SimpleClass) char tmp[SimpleClass_SIZE];
std::memcpy(&tmp, &s1, SimpleClass_SIZE);
// next line is OK under https://eel.is/c++draft/basic.types#general-2
// std::memcpy(&s1, &tmp, SimpleClass_SIZE);
// does https://eel.is/c++draft/basic.types#general-2 apply (not the original object)
std::memcpy(&s2, &tmp, SimpleClass_SIZE);
}
Obviously the intermediate array is useless but the original post was about swapping both objects value representations, thus the intermediate storage.
During the ensuing discussion, the consensus was that the code was valid under https://eel.is/c++draft/basic.types#general-2 and https://eel.is/c++draft/basic.types#general-3.
Yet https://eel.is/c++draft/basic.types#general-2:
For any object (other than a potentially-overlapping subobject) of trivially copyable type T, whether or not the object holds a valid value of type T, the underlying bytes ([intro.memory]) making up the object can be copied into an array of char, unsigned char, or std::byte ([cstddef.syn]).27 If the content of that array is copied back into the object, the object shall subsequently hold its original value.
(emphasis mine)
It guarantees that you can copy back to the same object but not to a different one. I think that the spirit would be to copy back into an object of same type but not necessarily the original one. IMHO, all compiler consider this construct as correct, which is meaningful.
Is it a ill-wording of the standard, is there another item for this situation or is it formally UB so far?
Upvotes: 0
Views: 83