Size of a class instance at compile time

Don Clugston dac at nospam.com.au
Sun Jan 14 23:53:18 PST 2007


Daniel Keep wrote:
> 
> Got it!  No, really, this time FOR SURE ^_^
> 
> The end solution is utterly evil, but is, AFAIK, correct.
> 
> What I had to do in the end was to say that the size of a class instance 
> is the maximum of:
> 
> 1) size of the base class + if(implements interfaces)
>            padding + interface count * pointer size,
> 2) max(class member alignof + sizeof) + if(implements interfaces)
>            padding + interface count * pointer size
> 
> I also added a minimum size of 2*pointer size to account for classes 
> that don't have any member variables.
> 
> Getting the padding for interfaces was fun:
> 
>  > struct Align
>  > {
>  >     ubyte a;
>  >     void* b;
>  > }
>  >
>  > const PTR_ALIGN = Align.tupleof[1].alignof;

Nifty!

> I *think* that's right.  In any case, it's reporting the correct size 
> for every test case I throw at it.  Anything else that needs fixing? :P

One other nasty case is where the last member of a class is an 80-bit 
real, with padding that is different between Windows, Linux32, and 
Linux64. Does that work correctly?

> 
>     -- Daniel
> 
> private
> struct Align
> {
>     ubyte a;
>     void* b;
> }
> 
> private
> const PTR_ALIGN = Align.tupleof[1].alignof;
> 
> private
> template AlignPad(size_t base, size_t aligned)
> {
>     static if( aligned == 0 )
>         const AlignPad = base;
>     else
>         const AlignPad = ((base+PTR_ALIGN-1)/PTR_ALIGN)*PTR_ALIGN
>             + aligned;
> }
> 
> template InstanceSize(T)
> {
>     static if( is( T == Object ) )
>         const InstanceSize = 2*(void*).sizeof;
>     else
>         const InstanceSize = Max!(
>             AlignPad!(
>                 InstanceSize!(Super!(T)),
>                 InterfaceCount!(T)*(void*).sizeof),
> 
>             AlignPad!(
>                 InstanceSizeImpl!(T, 0),
>                 + InterfaceCount!(T)*(void*).sizeof));
> }
> 
> private
> template Super(T)
> {
>     static if( is( T S == super ) )
>         alias First!(S) Super;
>     else
>         static assert(false, "Can't get super of "~T.mangleof);
> }
> 
> private
> template First(T)
> {
>     alias T First;
> }
> 
> private
> template First(T, Ts...)
> {
>     alias T First;
> }
> 
> private
> template InstanceSizeImpl(T, size_t i)
> {
>     static if( i < T.tupleof.length )
>         const InstanceSizeImpl = Max!(
>             T.tupleof[i].offsetof + T.tupleof[i].sizeof,
>             InstanceSizeImpl!(T, i+1));
>     else
>         // This is necessary to account for classes without member
>         // variables.
>         const InstanceSizeImpl = 2*(void*).sizeof;
> }
> 
> private
> template Max(size_t a, size_t b)
> {
>     static if( a > b )
>         const Max = a;
>     else
>         const Max = b;
> }
> 
> private
> template InstanceSizeAligned(T, size_t alignment)
> {
>     static if( alignment == 0 )
>         const InstanceSizeAligned = InstanceSize!(T);
>     else
>         const uint InstanceSizeAligned
>             = InstanceSizeAlignImpl!(T, alignment).result;
> }
> 
> private
> template InstanceSizeAlignedImpl(T, size_t alignment)
> {
>     private const base_size = InstanceSize!(T);
>     const result = ((base_size+alignment-1)/alignment)*alignment;
> }
> 
> private
> template InterfaceCount(T)
> {
>     static if( is( T == Object ) )
>         const InterfaceCount = 0u;
>     else static if( is( T S == super ) )
>         const InterfaceCount = InterfaceCountImpl!(S);
> }
> 
> private
> template InterfaceCountImpl(TBase, TInterfaces...)
> {
>     const InterfaceCountImpl = TInterfaces.length;
> }
> 


More information about the Digitalmars-d-learn mailing list