In various 3d math codebases I sometimes encounter something like this:
struct vec {
float x, y, z;
float& operator[](std::size_t i)
{
assert(i < 3);
return (&x)[i];
}
};
Which, AFAIK is illegal because implementations are allowed to spuriously add padding between members, even if they are of the same type, though none will do so in practice.
Can this be made legal by imposing constraints via static_assert
s?
static_assert(sizeof(vec) == sizeof(float) * 3);
I.e. does static_assert
not being triggered implies operator[]
does what is expected and doesn't invoke UB at runtime?
No, it is not legal because when adding an integer to a pointer, the following applies ([expr.add]/5):
If both the pointer operand and the result point to elements of the same array object, or one past the last element of the array object, the evaluation shall not produce an overflow; otherwise, the behavior is undefined.
y
occupies the memory location one past the end of x
(considered as an array with one element) so adding 1 to &x
is defined, but adding 2 to &x
is undefined.