Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it legal to cast a pointer to a partially constructed object to a pointer to a base class?

That is, is something like this always legal?

struct Derived;
struct Base { Base(Derived*); };
struct Derived : Base { Derived() : Base(this) { } };
Base::Base(Derived *self) {
    if(static_cast<Base*>(self) != this) std::terminate();
}

int main() {
    Derived d; // is this well-defined to never call terminate?
}

At the point that the static_cast is evaluated, self does not yet point to a Derived object—that object is under construction. E.g. if Derived had data members, their constructors would not have been called. Is the cast still guaranteed to be defined behavior, resulting in a pointer equivalent to Base's this (which does point to a fully constructed Base base class subobject)?

A standard quote that I think gets close to answering this is [conv.ptr]/3.

...The result of the conversion is a pointer to the base class subobject of the derived class object. ...

But I think there is no derived class object yet, so what happens? If it is indeed undefined, does the answer change for self != static_cast<Derived*>(this)?

(Clang and GCC compile and run this "as expected".)

like image 749
HTNW Avatar asked Aug 07 '21 01:08

HTNW


1 Answers

This is fine: [class.cdtor]/3 says

To explicitly or implicitly convert a pointer (a glvalue) referring to an object of class X to a pointer (reference) to a direct or indirect base class B of X, the construction of X and the construction of all of its direct or indirect bases that directly or indirectly derive from B shall have started and the destruction of these classes shall not have completed, otherwise the conversion results in undefined behavior. ...

It requires that the source type (and any other bases inheriting from the destination type) have begun its constructor and not have finished its destructor. Even the initializer for the base counts as beginning the derived constructor; the standard contains a very similar example.

like image 124
Davis Herring Avatar answered Oct 21 '22 19:10

Davis Herring