Enum to String in Unreal Engine: How I Learned to Stop Hardcoding and Love Type Safety
There are things, that come up time and time again. One of those things is creating a string version of Enum values in Unreal Engine. For this and other cases, we started to condense some of our utility and helper functions into a module. This module can then be used as part of a plugin, or as a standalone game module. In this article, I want to highlight our approach for to stringify enum values.
Imagine we want to log the value of an enum type called EWlanNotificationMSM. The API would look like this.
Let’s make this happen.
One of the goals I had in mind, when designing BIQStringify was the ability to work with a type safe call signature. Unreal Engine already provides a handy function for retrieving type information, called FindObject.
It expects you to specify the meta type (UEnum in this case) as template argument, the package root from which to search, the declaration name of the type and if the type should be matched exactly. Even if we abstract this now, passing the type as string is not really the type safe approach I had in mind. So next step is fetching type information.
Function call context
Luckily, most compilers define a context macro, allowing you to access the name of the current function. I abstracted the differences for compiling on Linux, Mac and Windows in a macro called CurrentFunctionName.
The approach here is using a specific predefined macro for each supported compiler environment. On Windows (MSVC) this would be __FUNCSIG__. On MacOS (clang) and Linux (GCC), the macro is __PRETTY_FUNCTION__. Let’s think back to our API example, and checkout how the function name would look like (using MSVC in this case.)
Looking at the value between <>, we Get enum EWlanNotificationMSM, which is excatly what we are looking for (minus the verbose type specifier enum). The function, preparing the actual name for later usage, is called GetNativeTypeName. Let’s look at the implementation.
It’s a template function, breaking up the function signature, to search for the name of the actual type instantiation of the template argument _Get_TypeName. When using MSVC, we also get a verbose type specifier, like enum, class or struct, which will be stripped by default, but can be retained if you like to.
Tying it all together
Enum Value Template Class
Now that we have access to the exact type name, we can make use of FindObject and implement a template class to manage enum value stringification.
The class simply takes the type via the template argument and queries the instantiated type name. The type name can then be used, to get the exact Unreal Engine meta data through UEnum and hold on to it. When ask to produce a string, we simply query the meta data for a string representation of the stored value and prepend the type name if bFullyQualified is true. To be able to let the compiler infer the type automatically, I created a shorthand template function called EnumValue. Et voilà!
Until next time my friends. Thank you for reading.