Feb 172015
 

Short answer: we don’t.

But it comes in handy.

Consider this code:

So, in case of an error this code might show the following message to the user:

“Could not connect to game server. Error: 19970829”

Wouldn’t it be better if the user got the following message instead?

“Could not connect to game server. Error: skynetTookOver”

No it wouldn’t !!! Everyone would panic!!!

You get my point. It is often useful to translate internal program data into something that the outside world can understand (or the other way around). And it would be nice if we could do so in an automated fashion, instead of having to hand-write all the “translation” code. This is actually what we call “reflection”.

Enum Reflection

In this article I’ll focus on enum reflection, because enums are simple and they are widely used. So you get an immediate benefit from reflection. In the next article I’ll write about general reflection of game objects.

To translate an enum value into a string we could write a function with a switch/case statement:

Easy enough, but this quickly becomes unmaintainable when you add new enum values as you have to do so in two places. It is also a source of errors if you forget to extend the function.

With the help of some boost preprocessor magic we can write a little macro that allows us to write this instead:

This declares the enum and makes it reflectable at the same time. Cool eh? When you get used to the syntax 😉
We can now use our enum like this:

It will print what you expect:

“Could not connect to game server. Error: skynetTookOver”

You can also use enumToStr() instead of boost::lexical_cast if a const char* is all you need.
To convert from string back to enum there is a strToEnum() function.

Auto-Magic

The macro also provides overloads of the stream operators << and >> so we can write an enum directly into a stream or read it back from there in string form. This is in itself very useful for writing human-readable logs.

Where it really shines though, is when you use enums with other libraries, like boost::property_tree. The property_tree class is very handy for reading and writing program configuration. When you declare an enum via the DECLARE_ENUM macro, you can put enum values directly into the property_tree and they will automagically be converted to string (or the other way around). A complete example:

This program simply writes an enum value into a JSON file and reads it back to verify it. Note that there isn’t any explicit conversion to string! It all works automagically because of the operator << and >> overloads provided by the DECLARE_ENUM macro. This example wouldn’t even compile if Fruit was just a “normal” enum declaration.

All of them

Also handy at times is the ability to iterate over the values of an enum. For instance, if you have a level editor, you may want to add all possible values of a game option to a combobox.

This would add the names of all 5 beater shapes to the combobox. If I later add more beater shapes, there is no need to modify the editor code at all!

There isn’t much more to it. To use this macro you only need to include a single 250 lines header, which you can download below. The only required dependency is the boost.preprocessor library (tested with version 1.58.0). For the enumValues template you also need boost.range and boost.iterator.

I leave it as an excercise for the reader to provide wchar_t support ;-).

Have fun and keep coding!

I want it!

Download EnumReflection.zip