Boost logo

Boost Users :

Subject: Re: [Boost-users] sizeof(boost::fusion:map)
From: Christopher Schmidt (mr.chr.schmidt_at_[hidden])
Date: 2010-11-06 08:17:42


alfC schrieb:
>
>
> On Nov 5, 9:49 pm, Joel de Guzman <j..._at_[hidden]> wrote:
>> On 11/6/2010 7:56 AM, Christopher Schmidt wrote:
>>
>>
>>
>>> Christopher Schmidt schrieb:
>>>> Robert Lupton the Good schrieb:
>>>>> I was very excited to find the boost::fusion library, expecting that I could use it to implement structs with introspection. I still think I can, but I was disappointed to see that I'm paying a size penalty. I'd have expected all the book-keeping to be handled at compile time.
>>
>>>>> The following code prints
>>>>> sizeof(Foo) = 12 sizeof(FooS) = 4
>>>>> with g++ 4.2 or 4.4 on an os/x 10.6 or Centos box.
>>
>>>>> Here Foo is
>>>>> boost::fusion::map<boost::fusion::pair<Name, int> >
>>
>>>> [snip]
>>
>>>> I have no idea why there is that space overhead. This problem is not
>>>> fusion specific, though.
>>
>>>> #include<iostream>
>>>> struct X{};
>>>> struct A:X{int i;};
>>>> struct B:X{A a;};
>>>> int main()
>>>> {std::cout<< sizeof(A)<< " "<< sizeof(B)<< std::endl;}
>>
>>>> When compiled with gcc 4.5.1 i686-pc-mingw32 and -O2, the output is "4
>>>> 8". When compiled with MSVC 2010 (x86) and /O2, "4 4" is printed.
>>
>>>> -Christopher
>>
>>> I think gcc is correct. There are two distinct instances of X in B, and
>>> those may not have the same address. That's why there is that 4 byte
>>> displacement.
>>> It is pretty much the same in Fusion. All inbuilt sequences and the
>>> vector data storage share a common base class - fusion::sequence_root -
>>> that's where the 4 resp. 8 bytes come from.
>>
>> Good analysis, Christopher. We should do something about this.
>> sequence_root is only there for easy tag detection. There should
>> be better way.
>
> Joel,
>
> If I am not wrong: this is related to a question I asked some weeks
> ago. When I was surprised (disappointed?) to find that
> fusion::vector<double, double, double> has a memory layout different
> than double[3] (or boost::array<double,3>). I didn't look at the
> 'sizeof' then but know that Robert mentions it I tried:
>
> std::clog << sizeof(double) << std::endl;
> std::clog << sizeof(vector<double, double, double>) << std::endl;
> std::clog << sizeof(boost::array<double, 3>) << std::endl;
>
> which in my platform emits:
>
> 8
> 28
> 24
>
> It would be interesting to know what does Boost.fusion stores in the
> extra bytes and why on earth neither the size nor the memory layout is
> the same as the contained data. It seems that the inconsistency on the
> size raises more eyebrows than the unexpected memory layout.
>

Nothing is stored in those 4 additional bytes.
As I said above one additional byte is added by the compiler to the
3*sizeof(double) bytes so one is able to distinguish between the two
instances of a common base class (fusion::sequence_root) of the vector
(fusion::vector<double, double, double>) and the internal vector data
storage (fusion::vector3<double, double, double>). To get size and
alignment right this one byte actually emits a 4-byte overhead on your
compiler.

-Christopher


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net