Sizeof two types of templates, when both of them are obtained from one base

Code example

#include <iostream> struct base {}; template<typename Type> struct left : base { Type value; }; template<typename Type> struct right : base { Type value; }; int main() { std::cout << "sizeof left<base> = " << sizeof(left<base>) << std::endl; std::cout << "sizeof left<right<base>> = " << sizeof(left<right<base>>) << std::endl; std::cout << "sizeof left<right<left<right<left<base>>>>> = " << sizeof(left<right<left<right<left<base>>>>>) << std::endl; } 

Exit

GCC 4.6 has

 sizeof left<base> = 2 sizeof left<right<base>> = 3 sizeof left<right<left<right<left<base>>>>> = 6 

With clang 3.1

 sizeof left<base> = 2 sizeof left<right<base>> = 3 sizeof left<right<left<right<left<base>>>>> = 6 

Since MSVC 2012

 sizeof left<base> = 1 sizeof left<right<base>> = 1 sizeof left<right<left<right<left<base>>>>> = 1 

So the question is whether this is a bug in GCC / clang, or is it a specific implementation, or is this the correct conclusion (quotes from the standard or explanations of this behavior will be nice)

+7
source share
2 answers

The corresponding quote is 1.8 [intro.object], paragraph 6:

If the object is a bit field or a subobject of a base class of zero size, the address of this object is the address of the first byte that it occupies. Two objects that are not bit fields can have the same address if one is a subobject of the other, or if at least one is a subobject of a base class with zero size, and they are of different types; otherwise they must have different addresses.

In the object right<T> and left<T> (why there should be enough classes for different class templates), you have a value member (of type T ). Everyone needs to get their own unique address. Thus,

 sizeof(left<right<left<right<left<base>>>>>) == 1 

definitely wrong! There are 6 different objects:

  • 5 value s
  • one left<right<left<right<left<base>>>>>

and only left<right<left<right<left<base>>>>> and one of its subjects (the first value , if I recall the other rules), can share the address. That is, the size of the object should be at least 5. Since the objects work best when aligned, it seems that they are filled up to 6 bytes (which is odd, I expect it to be complemented by a multiple of 4).

Even the size of the left<base> cannot be 1 : There are already two base objects! One in the form of a base class of objects lef<base> and one in form of a member of this class. These two lef<base> and one in form of a member of this class. These two base` needs different addresses, and thus the size must be at least 2.

In any case, the sizes of objects have only requirements, how important they are. They have no requirement that they be anything more. This is considered a matter of implementation quality. Based on this, the only compiler that is erroneous (provided that the quotation marks are indeed valid) is MSVC ++. Other sizes can sometimes be slightly larger than desired, but this is not a mistake.

+3
source

GCC's behavior is weird, but sizeof is completely a compiler, so it just depends on how the compiler is, as said you can try

 #pragma pack(1) 

and see the results again

0
source

All Articles