Reflection on Reflections (Part 1)
The holidays, always a good time for reflection ... and being a programmer, reflection of course can only possibly mean "the ability of a program to examine the type or properties of an object at runtime".
Yep, this is hardly breaking new ground but I have to amuse myself somehow. So why bother with reflection? Well it gives us some cool things, such as ...
- Automatic serialisation
Who likes writing loading and saving code? Or packaging data for a network stream? Surely there is more interesting code to write.
- Tool and script integration
Also, adding script bindings for functions or populating editor controls is a hardly a scintillating task. It would be nice if our classes integrated automatically with the rest of the game systems.
- Attaching additional attributes to variables
And for that matter, validating input or adding meta data (like ranges for values) should be be at least somewhat streamlined.
In short, type introspection simplifies of a lot of tedious and error prone stuff. And I for one am in favour of all things that mean I have to work less. Although somehow I always seem to spend more effort working less, go figure.
Now, if you are writing your game in a managed language (hello Unity) then you are probably wondering what all the fuss it about ... um, good point! I suggest you stop reading the rest of this drivel and actually go make yourself a game ...
Still here? OK, then lets go ahead and build this mousetrap! Down in C++ land we don't get much for free, but I guess we knew that already. The standard C++ gives us some limited RTTI if we actually turn it on, but where would the fun be in that.
To get to this fabled land where things happen automagically, we need a data model. A bunch meta-data that describes our types, names, fields, attributes and what have you.
The question is how do we create it.
We could hard code it all but that sounds like "work". We can do funky things with templates but this only gets us part of the way there (via a chunk of incomprehensible code). A separate "description file" is just one more thing to manage, and I wont even comment on the idea of trying to scrape symbols out of PDB files.
As I have already gone to the trouble of writing all that lovely (?) code in the first place, lets use that and whip up some meta-data as a pre-build step.
The usual approach here is to pop some special macros above various symbols that the tool picks up but the compiler ignores (à la mode de Unreal).
UPROPERTY(min=10, max=100) float ThisIsMySpecialFloat;
Apart from a few ugly macros, it seems solid but writing a tool to parse C++ properly, taking into account the language, pre-processor shenanigans and the like is not a simple task.
Fortunately, the clang guys and gals have already done all the hard work for me and gone to the trouble of wrapping it up into a convenient library to boot, which was nice :)
So that's the idea. Over the next couple of days, throw together some prototype code that utilises clang to do the heavy lifting. Then I can sit back and bask in the reflected glow of glorious meta-data ... and actually get on with the project I was meant to be working on before this sidetracked me!
Progress, after all, is made by lazy men trying to find an easier way to do something ... or something, I digress.