Interrupt-Driven


Elegant human readable enums

Posted in C++ by frank on the November 28th, 2008

While reading the source of some FOSS project i noticed that the authors have come up with a nice way to get human readable enums through the use of the “stringification feature” of the C/C++ preprocessor. The trick is that the members of the enum are declared through a macro which can be expanded in different ways.

  1. #include <iostream>
  2. #include <cstdlib>
  3. #include <cassert>
  4. #include <time.h>
  5.  
  6. namespace MyStuff
  7. {
  8.     enum Things {
  9.         #define THING(X) X,
  10.         #include "things.def"
  11.         MAX_THINGS
  12.     };
  13.  
  14.     static const char* const ThingNames[] = {
  15.         #define THING(X) #X,
  16.         //             ^ preprocessor stringification
  17.         #include "things.def"
  18.         NULL
  19.     };
  20.  
  21.     const char *toString(Things t) {
  22.         assert(t >= 0 && t < MAX_THINGS);
  23.         return ThingNames[t];
  24.     }
  25. }
  26.  
  27. int main(int argc, char **argv)
  28. {
  29.     using namespace MyStuff;
  30.     std::srand(::time(NULL));
  31.     for (int i = 0; i < 4; ++i) {
  32.         Things aRandomThing =
  33.             static_cast<Things>(std::rand() % MAX_THINGS);
  34.         std::cout << toString(aRandomThing) << std::endl;
  35.     }
  36. }
  37.  

things.def:

  1.  
  2. #ifndef THING
  3. #define THING
  4. #endif
  5.  
  6. THING(CELLPHONE)
  7. THING(NOTEBOOK)
  8. THING(CUP_OF_TEA)
  9. THING(MOUSE)
  10.  
  11. #undef THING
  12.  

Time after time i am amazed what you can do with some of the advanced preprocessor features like “token pasting” or stringification.


FireStats icon Powered by FireStats