How to retrieve UEnum by Type?

When I define an UEnum in C++ like this:

UENUM(BlueprintType)
enum class EMySampleEnum : uint8
{
	One,
	Two,
	Three
};

I’d like to be able to access its static UEnum instance like I’m used to with UStruct and UClass where a call to the ::StaticClass() member suffices to do this in a typesafe with no weird and error prone string hashing magic going on my side at least. As far as I can tell there is some code related to this generated in *.gen.cpp for hot reload purposes I suppose, but this doesnÄt seem to be accessible from the outside.

Is there a nice way to access the static UEnum instance corresponding to an enum type I have at hand?

I can’t use defines for this as I want to use this within templates aswell and defines are resolved before template parameters are.

In other words I’m looking for an implementation of GetStaticUEnum that could be used as follows:

template<typename T>
int32 GetMaxValue()
{
    return GetStaticUEnum<T>()->GetMaxEnumValue();
}

Hey!

Because of reflection system code need to know what type of enum you looking for…
You can do this using strings… Rama did a very good wiki page and described some usefull methods to get enums by strings using a template function…

I hope this helps or atleast good starting point :wink:

Rama’s Enum explanation

Sadly that doesn’t really answer my question. Once I’m in template code and only have the typename template parameter there is no way that I know of to convert this into a string matching the typename as it is used by the Rama there.

After stumbling on a similar issue, I was going through some source code and found an interesting function.
Currently I am using Unreal Engine 5.1 and I was looking in the source code of the following function :
https://docs.unrealengine.com/4.27/en-US/API/Runtime/CoreUObject/UObject/UEnum/GetValueAsName/1/
Which takes an enum value and returns the Enum name.

The source code contains the following lines :

static_assert(TIsEnum<EnumType>::Value, "Should only call this with enum types");
UEnum* EnumClass = StaticEnum<EnumType>();
check(EnumClass != nullptr);

Which does seems to fit our “convert static c++ type in UEnum instance” request, and with the ability to do error checking !

Edit: doc page of the function StaticEnum function :
https://docs.unrealengine.com/4.27/en-US/API/Runtime/CoreUObject/UObject/StaticEnum/

但是,我不知道为什么 StaticEnum 在编译的时候会报错…

    template<typename T>
    static FString GetEnumValueAsString(T EnumValue)
    {
        const UEnum* EnumPtr = StaticEnum<T>();
        if(EnumPtr)
        {
            FString EnumNameString = EnumPtr->GetNameStringByValue(static_cast<uint8>(EnumValue));
            return EnumNameString;
        }
        return TEXT("Invalid");
    }

报错如下:

  无法解析的外部符号 "class UEnum * __cdecl StaticEnum<enum EAssetFileType>(void)" (??$StaticEnum@W4EAssetFileType@@@@YAPEAVUEnum@@XZ),函数 "private: static class FString __cdecl FUpdateAutoAnalyzerModule::GetEnumValueAsString<enum EAssetFileType>(enum EAssetFileType)" (??$GetEnumValueAsString@W4EAssetFileType@@@FUpdateAutoAnalyzerModule@@CA?AVFString@@W4EAssetFileType@@@Z) 中引用了该符号

这是为什么呢,实在是没懂;

睡了一觉捣鼓一下明白了,有几个原因:

  1. 首先这个 StaticEnum<> 是在 “CoreUObject“ Module 下面的
  2. 在编译链接的时候,StaticEnum 用到的枚举 xxx 一定要用 UENUM() 修饰,才能运用反射
  3. 枚举的定义一定需要在 StaticEnum 能找到的地方,就我这个例子而言,我是在.h文件定义的模板函数 GetEnumValueAsString,但是我的枚举是定义在.cpp里面的,所以在编译的时候,模板实例化的时候会找不到枚举,所以会报错;

吐槽一嘴,这个报错也太不明显了,不清楚要表达什么…

Your enum should derive from uint8

example

UENUM()
enum class E_MyMovement : uint8
{
Walk,
Run,
Sprint
};

then you can create a uproperty

UPROPERTY(BlueprintReadWrite, EditAnywhere)
E_MyMovement Movement;

then if you need to get the string equivalent of the enum you can call

UEnum::GetValueAsString(Movement);

this will return a string value of the enum’s current value.