Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Reinterpret struct with members of the same type as an array in a standard compliant way [duplicate]

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_asserts?

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?

like image 900
yuri kilochek Avatar asked Jan 01 '17 21:01

yuri kilochek


2 Answers

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.

like image 97
Brian Bi Avatar answered Nov 20 '22 12:11

Brian Bi


Type aliasing (use of more then one type for essentially the same data) is a huge problem in C++. If you keep member functions out of structs and maintain them as PODs, things ought to work. But

  static_assert(sizeof(vec) == sizeof(float) * 3);

can't make accessing one type as another technically legal. In practice of course there will be no padding, but C++ isn't clever enough to realise that vec is an array of floats and an array of vecs is an array of floats constrained to be a multiple of three, and the casting &vecasarray[0] to a vec * is legal but casting &vecasarray[1] is illegal.

like image 24
Malcolm McLean Avatar answered Nov 20 '22 12:11

Malcolm McLean