c++c++20memcpytype-punningbit-cast

Why does bit cast require both types to be trivially-copyable?


Why does C++ std::bit_cast require both To and From to be trivially-copyable? For example:

From from{};
To to;
static_assert(sizeof to == sizeof from);
std::memcpy(&to, &from, sizeof to);

Here, to will be constructed from from without invoking a copy-constructor, so To obviously has to be trivially-copyable. On the other hand, as per definition, &from is taken as const void*, so none of its constructors would have to be called anyways. Therefore, as far as I can see, From does not really need to be trivially-copyable. And indeed, std::memcpy does not require anything to be trivially-copyable, but std::bit_cast does.

Why does the standard then impose this additional requirement and can it be safely avoided?

Note: this thread discusses why using std::memcpy on non-trivially-copyable types is undefined behavior, but only for the cases where To and From are the same type, and thus, requiring To to be trivially-copyable requires From to be trivially-copyable as well.


Solution

  • There isn’t any one strong reason, just several general concerns:

    1. symmetry (generally one would expect to be able to reverse such a function)
    2. virtual pointers (though, like other pointers, these could be disallowed only for constant evaluation)
    3. compatibility with std::memcpy (in the absence of any other official means of accessing and imbuing object representations)