Sunday, September 29, 2013

C++ enum.toString() and then some -- or "preprocessor metaprogramming is like, 'wow!', man"

So I have a simple enough problem. I have a series of named data objects

and a container class

where there are COUNT of these items, each with a name, type and default value, and the Initialise method where heap allocations are done outside the constructor -- it simply fills in the array with appropriately typed named values with their default values, and I want client code to be able to index the array with symbolic names.

Plain enums don't have a to-string (though there are tricks to auto-associate names with strings by simple preprocessor metaprogramming); to get a compile-time count there's the old stand-by of putting an extra dummy member at the end and a big fat comment about inserting new values above it.

C++11 enum classes don't give me anything over the older enums here. There are various enum-like classes out there, in varying degrees of complexity; these give type-safety (which I don't really need in this context), could be extended with extra data, can be iterated over -- but don't give a compile-time count.

Time to break out Boost for some industrial grade tooling, and be very glad that my compiler supports variadic macros.

I want to define my items one time, one place, no extras like

Let's start with basing our enum representation off the Boost MPL wrapper for size_t

with static initialization

and from there it's just a case of using the preprocessor metaprogramming to put the bits together, just iterating over the definitions to define all the types, their static initialization and the array initialization:

Then in the Items.h header file where I defined D and Items, realise the common parts:

and the Items.cpp file realises the initialisations

and consumers have a tolerable symbolic constant access to the values

while extending the list only has to happen in one place.

I'm just not sure if it's a bit too magic for the purpose.

No comments :