In the original proposal, that paragraph was written as: http://wg21.link/P0476r1
Returns: an object of type To whose object representation is equal to the object representation of From. If multiple object representations could represent the value representation of From, then it is unspecified which To value is returned. If no value representation corresponds to To's object representation then the returned value is unspecified.
So it seems like the intention was that padding bits are allowed to be changed. That is, there are multiple possible object representations for the same value representation of From with different padding, so there are multiple possible value representations in To with different values. For example, when bit_casting like this:
struct foo {
std::uint8_t a;
// 1 byte padding to align
std::uint16_t b;
};
bit_cast<std::uint32_t>(foo_value);
The padding byte is allowed to be different (so multiple bit_casts are allowed to return different values, but round-trip bit casting will conserve value in this case)
But there seems to be situations that break round-tripping. Consider this case (https://godbolt.org/z/KGTGes):
int a[1];
int b[1];
assert(std::begin(a) == std::end(b)); // 1
std::uintptr_t a_bits = std::bit_cast<std::uintptr_t>(std::begin(a));
std::uintptr_t b_bits = std::bit_cast<std::uintptr_t>(std::end(b));
assert(a_bits == b_bits); // 2
The first assertion is allowed to pass (And does in unoptimized builds). When it does pass, the second usually does too. When bit_cast back to int*, what index should be valid? [-1] to get the value of b[0] (if it is std::end(b)), or 0 for a[0] (if it is std::begin(a))? It seems to be unspecified
There are other cases where pointers can have the same value but be different. For an array T[N], casting its address, a T(*)[N], to void* will have the same value as casting a pointer to the first element, a T* to void*. The same happens when using an empty class member with [[no_unique_address]].