lundi 17 octobre 2022

Undefined Behavior in Unions with Standard Layout structs

Take the following code

union vec
{
    struct
    {
        float x, y, z;
    };

    float data[3];

    constexpr vec() : data{} {}
};

constexpr vec make_vec(float x, float y, float z)
{
    vec res;
    res.data[0] = x;
    res.data[1] = y;
    res.z = z;
    return res;
}

int main()
{
    constexpr vec out = make_vec(0, 1, 2);
    std::cout << out.z << '\n';
}

I make use of constexpr here to determine whether the code is undefined behavior or not, as the undefined behavior will cause a compilation error.

§9.2/19:

If a standard-layout union contains two or more standard-layout structs that share a common initial sequence, and if the standard-layout union object currently contains one of these standard-layout structs, it is permitted to inspect the common initial part of any of them.

From this, I would assume that everything in the code would be defined behavior.

Compiling with g++ main.cpp -o out -std=c++17, I get the message error: change of the active member of a union from 'vec::data' to 'vec::<anonymous>'.

I thought that to comply with the standard, I might've had to change it to this--

union vec
{
    struct
    {
        float x, y, z;
    };

    struct
    {
        float data[3];
    };

    constexpr vec() : data{} {}
};

But I get the same error.

Is this truly undefined behavior? Is there perhaps another part of the standard that I've missed, or am I simply misinterpreting the standard?

Aucun commentaire:

Enregistrer un commentaire