Skip to content

Instantly share code, notes, and snippets.

@awesomekling
Created May 24, 2020 11:41
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save awesomekling/6fec62b6a8a57264dfdc6e7e20290d93 to your computer and use it in GitHub Desktop.
Save awesomekling/6fec62b6a8a57264dfdc6e7e20290d93 to your computer and use it in GitHub Desktop.
Preprocessor enumeration macros in C and C++

Here's a trick to avoid repeating a list of things in multiple places:

#define ENUMERATE_THINGS \
    ENUMERATE_THING(Foo) \
    ENUMERATE_THING(Bar) \
    ENUMERATE_THING(Baz)

#define ENUMERATE_THING(thing) thing
ENUMERATE_THINGS
#undef ENUMERATE_THING

The code above will be expanded by preprocessor into this:

Foo
Bar
Baz

I often use this to declare large enums and making a stringification function for them like this:

enum class Thing {
#define ENUMERATE_THING(thing) thing,
ENUMERATE_THINGS
#undef ENUMERATE_THING
};

const char* to_string(Thing thing)
{
    switch (thing) {
    #define ENUMERATE_THING(thing) case Thing::thing: return #thing;
    ENUMERATE_THINGS
    #undef ENUMERATE_THING
    }
}

The code above will be expanded by the preprocessor to:

enum class Thing {
    Foo,
    Bar,
    Baz,
};

const char* to_string(Thing thing)
{
    switch (thing) {
    case Thing::Foo: return "Foo";
    case Thing::Bar: return "Bar";
    case Thing::Baz: return "Baz";
    }
}

This allows you to keep the canonical list of things in a single place, so you don't have to update multiple functions when adding a value.

(Note: The expanded code will actually look a bit different, whitespace-wise. The C/C++ parser doesn't care though, so I've made it look nice here for demonstration purposes.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment