March 26, 2005

Virtual sizeof

Do you ever wish you could do this:
class Base
{
};

class Derived: public Base
{
int x;
};

Base *p = new Derived;

size_t s = sizeof(*p); // s is sizeof(Derived)
Of course it doesn't work because s becomes the size of Base rather than Derived. What you really want is a kind of "virtual sizeof". This is what I came up with:
class Base
{
public:
virtual size_t Size() const = 0;
};

class Derived: public Base
{
int x;
};

template < typename T >
class Wrapper: public T
{
public
virtual size_t Size() const
{
return sizeof(T);
}
};

template < typename T >
T *New()
{
return new Wrapper< T >;
}

Base *p = New<Derived>();

size_t s = p->Size(); // works as desired

Comments:
I'd been troubled by this ever since I first read about it, for the simple fact that it's "extra stuff to remember." E.g. if you try MyThing* mt = new MyThing, you get compile errors that won't make it obvious what to do.

However, this morning I realized a solution that works for my own mad interpretation of The Right Thing.

template < class T >
T* Create()
{
return new Wrapper< T >;
}

and then, you make the ctors protected, and ding-dong, you're set.

So, you now have MyThing* mt = Create< MyThing >();, and voila. Sure this is a bit boilerplatey as well, but the user doesn't need to worry about the Wrapper class at all in this case, they just directly say "create this actual thing that I want, and don't worry that it's giving me a derived class in its stead."

(Some compilers will mis-link the function signature that I gave above, unfortunately. For those, change it to T* Create(T* =0).)
 
Ugh, now I see that's what you were getting at with the New template function. Doh! That'll teach me not to read the post for weeks before posting my own tidbit.

Still- as I said the boilerplate or "misdirection" as it were still rubs me the wrong way somewhat. I'd prefer something like MyThing* mt = MyThing::Create();, but that too requires support in the class itself which you're explicitly looking to avoid.

Myself, maybe I'd make a macro that said DECLARE_THE_JUNK, and was defined to provide bodies for those functions as appropriate. Despite all of the times I've done that, though, it too sits uneasily with me...
 
Nice job, I was looking for something similar to this.
Thanks.

-Echo
http://www.echo.net84.net/
 
Post a Comment

<< Home

This page is powered by Blogger. Isn't yours?