Standard Layout c++
Asked Answered
V

1

20

I was going through great articles on C++ POD, Trivial and Standard Layout classes One property I haven't clearly understood about standard layout is the following:-

 A standard layout has no base classes of the same type as the first 
    non-static data member

So the following will not be a Standard Layout as it has the first member same as the base class

struct NonStandardLayout3 : StandardLayout1 {
    StandardLayout1 x; // first member cannot be of the same type as base
};

But performance-wise and property-wise how is the above struct any different than

struct StandardLayout5 : StandardLayout1 {
    int x;
    StandardLayout1 y; // can have members of base type if they're not the first   
};

which is the correction of the one above this.

Vip answered 2/7, 2012 at 20:6 Comment(2)
Related post.Plastic
Possible duplicate of Why is C++11's POD "standard layout" definition the way it is?Pneumonectomy
R
18

The reason is that standard layout types effectively mandate the "empty base class optimization" where base classes with no data members take up no space and have the same address as the first data member (if any) of the derived class.

However, attempting doing this when the base class has the same type as the first data member violates the C++ memory model which requires that distinct objects of the same type must have distinct addresses.

From ISO/IEC 14882:2011 1.8 [intro.object]/6:

Two objects that are not bit-fields may have the same address if one is a subobject of the other, or if at least one is a base class subobject of zero size and they are of different types; otherwise, they shall have distinct addresses

effectively mandating the empty base class, 9.2 [class.mem] /20:

A pointer to a standard-layout struct object, suitably converted using a reinterpret_cast, points to its initial member (or if that member is a bit-field, then to the unit in which it resides) and vice versa.

It would be impossible for the following types (Type1 and Type2) to be layout-compatible (although they would otherwise be standard-layout classes) without this restriction.

struct S1 {};
struct S2 {};

struct Type1 : S1 {
    S1 s;
    int k;
};

struct Type2 : S1 {
    S2 s;
    int m;
};
Raye answered 2/7, 2012 at 20:19 Comment(5)
This is exactly what the footnote for this rule at §9/7 says too: "[This rule] ensures that two subobjects that have the same class type and that belong to the same most derived object are not allocated at the same address"Eligibility
Type2 was a standard-layout class according to C++14 and continues to be a standard-layout class according to N4606 and C++1z, as S1 is not the same type as S2.Conurbation
By "It would be impossible for the following types (Type1 and Type2) to be layout-compatible (although they would otherwise be standard-layout classes) without this restriction." do you mean that, according to the standard, Type1 and Type2 would be layout-compatible (because they are standard-layout classes), but practically it would be impossible to implement them as such (due to the first quote in your post: [intro.object]/6)? Thank you.Substation
I kept reading your last paragraph, the one that I cited in my previous comment, in order to make sure I understand it correctly. By "without this restriction" you refer to "9.2 [class.mem] /20", the restriction which mandates that a standard-layout object must have the same address as its first member, correct? This restriction combined with "1.8 [intro.object]/6" makes it impossible for a type T whose first member has type U, and its base class also has type U, to be a standard-layout type. [continued]Substation
@CharlesBailey So your last paragraph states that "without this restriction" ("9.2 [class.mem] /20"), Type1 and Type2 could not be layout-compatible. Without "9.2 [class.mem] /20", Type1 and Type2 would be standard-layout types, and according to the rest of the definitions in the standard they would be layout-compatible. However, one could not implement them to be layout-compatible, even if the standard says that they are, because they do not have the same memory layout. Is this what you meant? Thank you and I apologize for insisting.Substation

© 2022 - 2024 — McMap. All rights reserved.