What options, if any, do I have to use an enum in C++ that supports reordering/inserting/removing of enum values?

Both FName and FGameplayTag fill your requirements.

Ignoring FGameplayTag “for perf reasons” likely stems from a misunderstanding of how it works - gameplay tags aren’t strings, they’re backed by FName with some extra functionality. And names are stored as an index into a global table of strings. Comparing names is quick as you’re comparing indices into that table, not iterating strings. Hashing and just about every other operation is the same way up until you need to do real string operations on them (which involves getting a real string rather than doing anything with the name/gameplay tag, but this isn’t any slower than what you’d need to do with an enum anyway).

Initial creation of names from strings is slow (relative to simply assigning an enum value), but you can either use gameplay tags (which must be defined by engine startup and shouldn’t be created or looked up at runtime if you can help it) or reference static instances of names from code. So you should really only have to pay that cost on startup.

If you really want something based on actual enums it’d be possible to wrap your enums with a custom USTRUCT that has its own serialization/deserialization methods. You’d need to make a wrapper for every enum you want to work this way, however.

Some further reading:

1 Like