Home > front end >  Is swapping a const member undefined behavior? C 17
Is swapping a const member undefined behavior? C 17

Time:04-15

https://godbolt.org/z/E3ETx8a88

Is this swapping UB? Am I mutating anything? UBSAN does not report anything.

#include <utility>

struct MyInt
{
    MyInt(int ii): i(ii) {}
    const int i;
    MyInt& operator=(MyInt&& rh)
    {
        std::swap(const_cast<int&>(i), const_cast<int&>(rh.i));
        return *this;
    }
};

int main() {
    MyInt i0(0);
    MyInt i2(2);

    i0 = std::move(i2);
    return i0.i;
}

CodePudding user response:

Is this swapping UB?

Yes, this is UB.

Am I mutating anything?

You are mutating const objects. That's not allowed.

CodePudding user response:

This seems to be an area of c evolution.

It's UB in c 17 because of this restriction on replacing const member objects

However, in later versions, this restriction is mostly removed.. There remains a restriction on complete const objects. For instance you can't do this if MyInt i0(0); was const MyInt i0(0);

Even though c 20 now allows modification of const sub objects, it's best to avoid const_cast and use this to create an assignment ctor. In this case one doesn't need a destructor since it's trivially destructable. Note that one had to use placement new prior to c 20 and that was still UB since const sub objects were not permitted to change previously.

constexpr MyInt& operator=(MyInt&& rh)
{
    std::construct_at(&this->i, rh.i);
    return *this;
}

CodePudding user response:

From const_cast

Modifying a const object through a non-const access path and referring to a volatile object through a non-volatile glvalue results in undefined behavior.

so Yes, that is UB.

  • Related