Const casting empty base class
Asked Answered
P

1

6

Is it undefined behavior to const_cast away an empty base class and call a non const method on it? For example

class EmptyBase {
public:
    void bar() { ... }
};

class Something : public EmptyBase {
public:
    void foo() const {
        const_cast<EmptyBase&>(static_cast<const EmptyBase&>(*this)).bar();
   }
};

I haven't been able to find relevant information in the standards (C++14 and C++17) that answers this..

Phillis answered 21/12, 2017 at 6:43 Comment(7)
Do you mean EmptyBase::bar(); in void foo() const?Jacquiline
so ::bar would in effect be a static memberfunction?Batson
See section "7.1.6.1 The cv-qualifiers", sentence 4. It gives examples.Hylo
@Jacquiline not really, editedPhillis
@Batson ^ no, a member functionPhillis
@WernerHenze of which standard? Did you mean [basic.type.qualifier]? Also was that directed to me?Phillis
@Phillis Yes, directed to you. I looked into "ISO/IEC JTC1 SC22 WG21 N3690, Date: 2013-05-15", which is a bit out of date. In the current standard (see timsong-cpp.github.io/cppwp) I see it at 10.1.7.1. The examples are not exactly matching your question, but they show when you can write to the const_cast pointer.Hylo
C
8

It's not UB in and of itself. You get undefined behavior when you cast away constness and use the obtained glvalue to modify an object which is originally declared const. Here's the standard quote on this ([dcl.type.cv]/4):

Except that any class member declared mutable can be modified, any attempt to modify a const object during its lifetime results in undefined behavior.

Merely calling a member function is not a modification of an object. It all depends on what the function does. So if it does something crazy like:

std::memset(this, 0, sizeof(*this));

That would result in undefined behavior, for sure. But assuming it doesn't, and since there are no members for it to modify in an ill-formed manner, there is no UB from the call.

The other question, of whether or not it's a good idea, has an obvious answer. Const casts should not litter code bases. But if the base class is well-behaved, albeit not well-defined, it may be acceptable if you can't change the class.

Calloway answered 21/12, 2017 at 6:56 Comment(3)
Wouldn't this be an EmptyBase* in this context, and sizeof(*this) be 0?Palliative
@Palliative - No. sizeof may not return 0 for any object type in a well formed program. Inside the member function, it will consider *this the "complete" object. So sizeof would likely return 1. In effect, it means you'll be thrashing the memory of Something.Calloway
I see. I've found the related en.cppreference.com/w/cpp/language/eboPalliative

© 2022 - 2024 — McMap. All rights reserved.