Download

FArchive Enum

Hello All.

What is the proper way to archive (serialize, and deserialize) enumerations? For some reason I am not able to include them in the stream.

I have several enum’s defined at the global namespace, all contained within a single header file, and of the format:



    UENUM(BlueprintType)
    enum class EditMode : uint8
    {
        Add             UMETA(DisplayName = "Add"),
        Modify          UMETA(DisplayName = "Modify"),
        View            UMETA(DisplayName = "View"),
        Delete          UMETA(DisplayName = "Delete")
    };


And from this I attempted to use the below in the same header file:



    FORCEINLINE FArchive& operator<<(FArchive& ar, EditMode& editMode)
    {
        ar << editMode;
        return ar;
    }


Unfortunately I get bazaar errors:



'operator<<' : recursive on all control paths, function will cause runtime stack overflow
:
:
'operator<<' : recursive call has no side effects, deleting


Can someone provide any insight into this?

Thank you for your help.

Serializing Enum as Byte (inside a USTRUCT)

Dear Community and Jerry,

Here’s a system I’ve used in the past for serializing enums.

I wrote this up quickly just for you and anyone else who read this :slight_smile:

I used this method to serialize BP-exposed Enums in Solus quite successfully so I know it works :slight_smile:

Including the USTRUCT is not necessary, I was just demoing the chain of operator<< overloads and also making sure it all compiled properly :slight_smile:



UENUM(BlueprintType)
enum class ENature : uint8
{
	Trees          	UMETA(DisplayName = "Trees"),
	Streams      	UMETA(DisplayName = "Streams"),
	Flowers     	UMETA(DisplayName = "Flowers"),
	Rivers         	UMETA(DisplayName = "Rivers")
};
	
USTRUCT()
struct FNatureStruct
{
	GENERATED_USTRUCT_BODY()
	
	UPROPERTY()
	ENature Nature1;
	
	FNatureStruct(){}
};

FORCEINLINE FArchive &operator<<(FArchive &Ar, ENature& TheEnum)
{ 
	uint8 AsByte = (uint8)TheEnum; 	//When saving

        //Serialize as byte
	Ar << AsByte;			
	
	//Loading
	if(Ar.IsLoading())
	{
		TheEnum = (ENature)AsByte; //When loading
	} 
	 
	return Ar;
}
FORCEINLINE FArchive &operator<<(FArchive &Ar, FNatureStruct& TheStruct)
{ 
	Ar << TheStruct.Nature1;
	 
	return Ar;
}



**<< Operator Goes Both Ways**

Remember the << operator is used during both loading and saving, that's why I have to make sure that both saving and loading are covered inside the operator:



```


FORCEINLINE FArchive &operator<<(FArchive &Ar, ENature& TheEnum)
{ 
	uint8 AsByte = (uint8)TheEnum; 	//When saving

        //Serialize as byte
	Ar << AsByte;	
	
	//Loading
	if(Ar.IsLoading())
	{
		TheEnum = (ENature)AsByte; //When loading
	} 
	 
	return Ar;
}


```



Thank You for Enum Extending Byte !

This is all even easier now that we have the wonderful new enum syntax that extends directly from uint8! Thanks Epic!

I hope you find this useful Jerry and everyone!

Enjoy!

Rama

Thank you Rama. Based on your example I have the following that appears to work:



if (ar.IsSaving())
{
     uint8 val = (uint8)data.myType;
     ar << val;
}
else
{
    uint8 val;
    ar << val;
    data.myType = (MyEnumType)val;
}


May I ask how would you handle TArray<enum> myArray?

If I try to define the operator<< for the different enumerations I get the bazaar error that I mentioned above.

To get around the errors I am converting the enumerations “up” a level in the stream instead of relying on the operator overload.

Hello,

Just in case this helps, it seems that when declared as a TEnumAsByte, everything is handled gracefully.
The following code works for me:


UENUM()
enum ObjectMeshTypeEnum
{
	OBJECT_MESH_TYPE_CUBE,
	OBJECT_MESH_TYPE_MODEL,
	OBJECT_MESH_TYPE_EFFECT
};

-------------------------------------------------------------------

UPROPERTY()
	TEnumAsByte<ObjectMeshTypeEnum> MeshTypeEnum;

-------------------------------------------------------------------

Ar << MeshTypeEnum;

Cheers

Cedric

I use class-based enums now instead, they’re much easier to work with than the TEnumAsByte workaround, and you get some level of control over their size as well (sizeof)