I have a class whose purpose is to move data which might have alignment restrictions to or from a serialized memory buffer where the data is not aligned. I have set and get handlers as follows:
#include <cstring>
template<typename T>
struct handle_type {
static inline T get(const void *data) {
T value;
memcpy(&value, data, sizeof(T));
return value;
}
static inline void set(void *data, T value) {
memcpy(data, &value, sizeof(T));
}
};
After c++20 comes out, I am hoping it will become something like the following:
#include <bit>
template<typename T>
struct handle_type {
union unaligned { char bytes[sizeof(T)]; }; // EDIT: changed from struct
static inline T get(const void *data) {
return std::bit_cast<T>(*(const unaligned*)data);
}
static inline void set(void *data, T value) {
*(unaligned *)data = std::bit_cast<unaligned>(value);
}
};
Will it work? Or is the fact that I am using an inerim type, the unaligned struct type, liable to pose a problem?
Your get
function is UB unless the user has provided a pointer to an unaligned
object. Your set
function is similarly UB unless data
is an unaligned
object. Either of these cases violates strict aliasing. Remember: the strict aliasing back-door is about an actual char*
; that's not the same as an object that happens to contain a char*
.
Also, set
is potentially a compile error, depending entirely on whether or not the implementation of unaligned
is such that it has the same size as T
. After all, unaligned
may have padding at the end.
bit_cast
wants to deal primarily in objects, not random buffers of memory. For that, you should stick with memcpy
.
<changed to use
union
instead ofstruct
>
That changes nothing; using a union
doesn't guarantee that the size of the union
is equal to the size of its largest data member. From [class.union]/2:
The size of a union is sufficient to contain the largest of its non-static data members.
Emphasis added: "sufficient", not "equal to". The standard permits implementations the ability to make the union larger than its largest data member, as such a size would still be "sufficient".