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
I'm not dead
It's been 3 weeks since my last post. I'm not dead. I've been busy working on various projects. None of them are in a state that I can post anything concrete. Last week I learned two scripting languages: Ruby and Lua. The first thing I noticed was how much more productive I was using a scripting language than C# or C++. I think it was mostly the dynamic typing and certain language features like closures and coroutines. Closures are awesome. They do all the things I wish C# delegates would do.
After writing my first program in Ruby, another thing I noticed was how short it was considering the amount of stuff it did. I also noticed that the code was considerably narrower than a C# or C++ program would be, probably because of all the type conversions I would have used in a statically typed language. Overall I think the Ruby program had about one quarter the surface area :)
Apart from that I've been thinking about next generation of consoles, parallel processing in particular. Nothing to report yet.
Today I messed around trying to write a C++ garbage collector. I discovered a diabolical way to abuse the assignment operator. Unless you tell it not to, a C++ compiler will automatically generate an assignment operator (and various constructors) for each class. This default assignment operator will assign member variables component-wise. So if you use smart pointers to represent references between objects, and override the smart pointer's assignment operator, it is possible to use the assignment operator of the containing class to find all the reference members.
Of course, this will only work if you write classes in a certain way. In particular, all the members have to handle being assigned to themselves. I can see STL containers going a bit funny. Still, it's keeping me entertained.
After writing my first program in Ruby, another thing I noticed was how short it was considering the amount of stuff it did. I also noticed that the code was considerably narrower than a C# or C++ program would be, probably because of all the type conversions I would have used in a statically typed language. Overall I think the Ruby program had about one quarter the surface area :)
Apart from that I've been thinking about next generation of consoles, parallel processing in particular. Nothing to report yet.
Today I messed around trying to write a C++ garbage collector. I discovered a diabolical way to abuse the assignment operator. Unless you tell it not to, a C++ compiler will automatically generate an assignment operator (and various constructors) for each class. This default assignment operator will assign member variables component-wise. So if you use smart pointers to represent references between objects, and override the smart pointer's assignment operator, it is possible to use the assignment operator of the containing class to find all the reference members.
template < typename T >
class SmartPointer
{
public:
SmartPointer &operator=(const SmartPointer &p)
{
if (garbageCollecting)
{
handlePointer(*this);
}
object = p.object;
return *this;
}
// ...
};
class MyClass
{
SmartPointer< OtherClass > p;
};
MyClass myObject;
garbageCollecting = true;
// Assigning myObject to itself causes handlePointer to
// be called for myObject.p
myObject = myObject;
Of course, this will only work if you write classes in a certain way. In particular, all the members have to handle being assigned to themselves. I can see STL containers going a bit funny. Still, it's keeping me entertained.
March 05, 2005
CDL prototype working
I just got my prototype CDL metacompiler working. It can compile the CDL class definition I posted previously and it outputs all the automatically generated schema and C++ serialization code. It's not even close to being production ready but I have taken it far enough to satisfy myself that it would be feasible for a game project. It was pretty straightforward to get working: just 18 hours.
I ended up not using the Puma C++ transformation library. It was overkill for my needs. I used the Program Database Toolkit instead. PDT is based on the EDG C++ compiler, which is used by a lot of commercial C++ compilers including Comeau C++. EDG can successfully compile boost (which gives a lot of compilers difficulty) so my metacompiler could compile class definitions that used boost or other template heavy code.
EDG is commercial, but they allow it to be used free for non-commercial purposes. I haven't been able to find out what kind of licensing arrangements are available. Alternatively, I could base CDL on Puma as originally planned. It would just be a little more work and I don't know if it would be able to parse things like boost.
I originally started considering this as an alternative to my C# to C++ translator for exploiting metadata and automatic code generation in game projects. I think they could both be made to work, although C# would offer more benefits. Of course, the CDL metacompiler is much simpler and much lower risk.
I think for my next project I will look at some scripting languages: their applications in games and how to effectively bind them to game code, possibly using CDL to automatically generate the bindings from annotated class definitions.
I ended up not using the Puma C++ transformation library. It was overkill for my needs. I used the Program Database Toolkit instead. PDT is based on the EDG C++ compiler, which is used by a lot of commercial C++ compilers including Comeau C++. EDG can successfully compile boost (which gives a lot of compilers difficulty) so my metacompiler could compile class definitions that used boost or other template heavy code.
EDG is commercial, but they allow it to be used free for non-commercial purposes. I haven't been able to find out what kind of licensing arrangements are available. Alternatively, I could base CDL on Puma as originally planned. It would just be a little more work and I don't know if it would be able to parse things like boost.
I originally started considering this as an alternative to my C# to C++ translator for exploiting metadata and automatic code generation in game projects. I think they could both be made to work, although C# would offer more benefits. Of course, the CDL metacompiler is much simpler and much lower risk.
I think for my next project I will look at some scripting languages: their applications in games and how to effectively bind them to game code, possibly using CDL to automatically generate the bindings from annotated class definitions.