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