Throwing my 2 cents here i’ve came with the following:
template<typename T>
static FString EnumToString(T Enum);
It only requires the enum type (absolutely no string and value). It can be used like this:
UYourFunctionLibrary::EnumToString<EBlockMode>(Mode);
Visual studio implementation (in GCC you can use PRETTY_FUNCTION)
template<typename T>
static FString EnumToString(T Enum)
{
#if !WITH_EDITOR
return "";
#else
static FString EnumName;
static bool bEnumNameInit = false;
// Init it once
if (bEnumNameInit == false)
{
bEnumNameInit = true;
FString FunctionSignature(__FUNCSIG__);
UE_LOG(LogRPG, Display, TEXT("Enum funcsig: [%s]"), *FunctionSignature);
int32 FirstIDX = FunctionSignature.Find(TEXT("(enum "), ESearchCase::CaseSensitive, ESearchDir::FromEnd);
if (FirstIDX != INDEX_NONE)
{
FirstIDX = FirstIDX + 6;
int32 LastIDX = (FunctionSignature.Len() - 1);
if (FunctionSignature.IsValidIndex(FirstIDX) && FunctionSignature.IsValidIndex(LastIDX) && FirstIDX < LastIDX)
{
EnumName = FunctionSignature.Mid(FirstIDX, LastIDX - FirstIDX);
UE_LOG(LogRPG, Display, TEXT("Enum name: [%s]"), *EnumName);
}
}
}
if (EnumName.IsEmpty())
return FString("ENUM_Invalid");
// const UEnum* EnumPtr = FindObject<UEnum>(ANY_PACKAGE, (const TCHAR *)(typeid(T).name()), true);
const UEnum* EnumPtr = FindObject<UEnum>(ANY_PACKAGE, *EnumName, true);
if (!EnumPtr)
return FString("ENUM_Invalid");
#pragma warning(disable: 4996)
return EnumPtr->GetDisplayNameText(static_cast<int32>(Enum)).ToString();
#endif
}
I’m sure there’s some template master out there that can transform the usage of FUNCSIG into a constexpr, but the enum name is extracted only once. Note that I’m using it for debugging only, high performance is not a top priority for me.