跳到主要內容

Stringify C++ Enum Safely

Stringify Enum Safely

Sometimes stringifying C/C++ enumerator, or enum, values within its literal names are useful for debugging or logging. In this article, I’ll share how I achieve basic enum stringify and how to do it safely against changes to enum definitions.

Basic Idea

Given a boring enum Result as follows.

enum class Result : int8_t {
  OK = 0,
  FAILED,
};

My usual way to stringify them is using a table, i.e.

#define STR(X) #X
char const* StringifyResult(Result res) {
  char const* str[] = {
    STR(OK),
    STR(FAILED),
  };
  return str[static_cast<std::underlying_type_t<Result>>(res)];
}
int main() {
  printf("%s", StringifyResult(Result::OK)); // print "OK"
}

It benefits us from simplicity - simply copy’n paste those enum values then decorate them with STR(). Tons of editors can accomplish such editing in a snap.

Check Consistency

Occasionally we may change an enum definition - changes include adding, removal, and renaming. For first two cases, add a LAST enum value to end of an enum definition and static_assert the enum size. i.e.

#define STR(X) #X
enum class Result : int8_t {
  OK = 0,
  FAILED,
  LAST,
};
char const* StringifyResult(Result res) {
  char const* str[] = {
    STR(OK),
    STR(FAILED),
  };
  static_assert(Result::LAST == sizeof(str)/sizeof(char const*));
  // ...
}

In case of renaming, enhance the macro STR, to validate correct enum value names, with comma operator. i.e.

#define STR(Enum, X) ((void)Enum::X, #X)

Then apply the macro, e.g.

STR(Result, OK) // Expand as ((void)Result::OK, "OK")
  • The first operand, (void)Enum::X, of comma operator makes sure that the name X is a valid identifier of Enum and causes compile error if it’s not.
  • (void) suppresses compile warning/error of unused expression result.
  • If the first operand was compiled correctly, then #X is the final result of the comma expression.

Finally, whenever definition of an enum is changed, we get a compile error if the stringify function does not cover all enum values with valid names.


Written with StackEdit.

留言