I'm trying to understand when I can safely cast a derived object to a base subobject through a pointer to void (I think it should be the same as reinterpret_cast
). But the Standard's wording on this, which I could find, confuses me. First of all,
Two objects a and b are pointer-interconvertible if:
— one is a standard-layout class object and the other is the first non-static data member of that object, or, if the object has no non-static data members, the first base class subobject of that object
From this one cannot draw a reliable conclusion whether "or" applies to the whole subsentence before "or" or only to the second part of it. This is important because I can't know for sure if "standard-layout class object" is imperative for pointer-interconvertibility with the base subobject in the case of absence of non-static data members.
But while digging in the Standard further I've found:
If a standard-layout class object has any non-static data members, its address is the same as the address of its first non-static data member. Otherwise, its address is the same as the address of its first base class subobject (if any).
This seems to be more clear that "standard-layout" is required. But still confusing. Consider the following code:
class B { public: int b; };
class C : public B { public: int c; };
int main ()
{
C c;
B* b = &c;
std::cout << &c << " address of standard-layout class object\n";
std::cout << &c.c << " address of its first non-static data member\n";
std::cout << b << " address of first base class subobject\n";
return 0;
}
On VS2019 the result is:
009BFBF8 address of standard-layout class object
009BFBFC address of its first non-static data member
009BFBF8 address of first base class subobject
which is not what the Standard says. Can you explain me this?
The point is in definition of standard-layout class. From http://www.cplusplus.com/reference/type_traits/is_standard_layout/:
A standard-layout class is a class (defined with class, struct or union) that:
has no virtual functions and no virtual base classes.
has the same access control (private, protected, public) for all its non-static data members.
either has no non-static data members in the most derived class and at most one base class with non-static data members, or has no base classes with non-static data members.
its base class (if any) is itself also a standard-layout class.
And, has no base classes of the same type as its first non-static data member.
In you example class C does not match the third rule and so it is not a standard-layout class.
Also, about your question about 'or', it applies only to the second part, i.e. after 'or' the statement is still about standard-layout class object, but without non-static members.