以符合标准的方式使用与数组相同类型的成员重新解释struct

yur*_*hek 9 c++ strict-aliasing language-lawyer type-punning structure-packing

在各种3d数学代码库中,我有时会遇到这样的事情:

struct vec {
    float x, y, z;

    float& operator[](std::size_t i)
    {
        assert(i < 3);
        return (&x)[i];
    }
};
Run Code Online (Sandbox Code Playgroud)

其中,AFAIK是非法的,因为允许实现在成员之间虚假地添加填充,即使它们属于同一类型,但实际上没有人会这样做.

通过static_asserts 施加约束可以使这变得合法吗?

static_assert(sizeof(vec) == sizeof(float) * 3);
Run Code Online (Sandbox Code Playgroud)

static_assert没有被触发意味着operator[]什么是预期的并且不会在运行时调用UB?

Bri*_*ian 6

不,这是不合法的,因为在向指针添加整数时,以下适用([expr.add]/5):

如果指针操作数和结果都指向同一个数组对象的元素,或者指向数组对象的最后一个元素,则评估不应产生溢出; 否则,行为未定义.

y占用一个超过结尾的内存位置x(被视为具有一个元素的数组),因此&x定义了添加1 ,但是&x未定义添加2 .

  • @yurikilochek:你问过标准的说法.这就是它所说的. (3认同)
  • @yurikilochek:你可以推进`&y`,因为标准是这样说的.你不能推进`&x + 1`,因为标准是这样说的."&y"可能确实与"&x + 1"具有相同的值这一事实与标准所说的那些表达式无关*. (3认同)