As currently specified, bit_cast from an indeterminate value produces an unspecified value rather than an indeterminate value. That means this can't be implemented by a simple load on some implementations, and instead will require some kind of removing-the-taint-of-an-uninitialized-value
operation to be performed. (A similar concern applies to reading from padding bits.)
Is that the intent?
I chatted with JF about this. The intent is as follows:
* bits of the input that don't have defined values result in the corresponding bit of the output being "bad"
* if any part of a scalar object is "bad", that object has an indeterminate value
Some examples:
struct A { char c; /* char padding : 8; */ short s; };
struct B { char x[4]; };
B one() {
A a = {1, 2};
return std::bit_cast<B>(a);
}
In one(), the second byte of the object representation of a is bad. That means that the second byte of the produced B object is bad, so x[1] in the produced B object is an indeterminate value. The above function, if declared constexpr, would be usable
in constant expressions so long as you don't look at one().x[1].
A two() {
B b;
b.x[0] = 'a';
b.x[2] = 1;
b.x[3] = 2;
return std::bit_cast<A>(b);
}
In two(), the second byte of the object representation of b is bad. But a bit_cast to A doesn't care because it never looks at that byte. The above function returns an A with a fully-defined value. If declared constexpr, it would produce a normal, fully-initialized
value.
int three() {
int n;
return std::bit_cast<int>(n);
}
In three(), the entirety of n is bad. A bit_cast from it produces an int whose value is indeterminate. And because we have an expression of non-byte-like type that produced an indeterminate value, the behavior is undefined.