Size of a class instance at compile time

Daniel Keep daniel.keep+lists at gmail.com
Sun Jan 14 20:27:40 PST 2007


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;

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

	-- 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