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