Strongly typed enums and switch statements

I have a ID system set up in each of my classes that was simply public string id{private set; get;} in a C# prototype I made in Unity. This is a puzzle game that randomizes sets, each puzzle has an ID 1A, etc… for example and sets are identified by concatenating the string, 1A + 2B = 1A2B for example. Each set ID has a name to it to help better identify which set of puzzles is currently in play and I’ve accomplished this with a switch

switch(puzzleA.ID + puzzleB.ID){
	case "1A1B" :
		puzzleSet = names[0];
		break;
	case "1A2B" :
		puzzleSet = names[1];
		break;
	case "1A3B" :
		puzzleSet = names[2];
		break;
    case "1A4B" :
	    puzzleSet = names[3];
	    break;
    ...

I’m trying to translate this into C++ Unreal without completely re-engineering the logic.

Since std::string or FString can’t be used in a switch in C++, I made a strongly typed enum and assigned each ID a unique int value so when two IDs are combined it will produce a unique int identifying the set like it did with strings in C#.

IDs are now ints in the following:

switch(puzzleA->GetID() + puzzleB->GetID()){
	case PuzzleID::_1A1B :
		this->puzzleSet = names[0];
		break;
	case PuzzleID::_1A2B :
		this->puzzleSet = names[1];
		break;
	case PuzzleID::_1A3B :
		this->puzzleSet = names[2];
		break;
	case PuzzleID::_1A4B :
		this->puzzleSet = names[3];
		break;

The compiler error I’m getting that I don’t understand is error: could not convert '_2A3B' from 'PuzzleID' to 'int' case PuzzleID::_2A3B :
I get that they’re now a type PuzzleID, but I thought the point of enums was to assign an int to some identifier.

you want 2 IDs to result in a third ID? you don’t need enums or switch cases to make that happen.

the 2 IDs could be strings, concatenate them, then convert the result to an FName, then use Find on a TArray of Fnames, to get an index integer, which you can use to access another TArray of FNames, to get your final result.

or combine the 2 TArrays into a TMap, for even faster hash table lookup.

That seems like a more logical way to do it. I just have to figure out how to use a TMap. My intention with a switch was faster look up because making 16 comparisons in a if-statement wasn’t working well.

the difference in speed between a “switch” vs “if-else” is negligible. the real problem comes from maintenance and lack of real time support. with the array search method, its extremely fast, but also dynamic at runtime, so you can expand your dictionary from blueprints, without changing the c++ code. in other words, its low maintenance and future proof, because it separates data from logic.

Strongly typed enums aren’t allowed to be converted to anything but the enum by default:

https://en.wikipedia.org/wiki/C%2B%2B11#Strongly_typed_enumerations

So, if you want to convert them to an Int, you would need to do something like:

case static_cast<int>(PuzzleID::_1A1B):
      // Do code stuff.

However, I think managing an ENUM that has the combined values for your puzzles is going to be a bit messy/confusing. Your string approach is valid, you just need to tweak it a bit. For example, one you have your combined string (e.g. “1A1B”), you could turn it into a unsigned int like so:

#include "Misc/Crc.h"

// ...

FString myPuzzleName = PuzzleA->GetName() + PuzzleB->GetName();
const uint myPuzzleID = FCrc::StrCrc32(myPuzzleName);

// You could then compare this ID in a switch with a set of pre calculated valid puzzle names that you populate when your game starts.

// Let's assume you have an array of uint validPuzzles[PuzzleID::TotalPuzzles] which is just that.

switch(myPuzzleID)
{
    case validPuzzles[PuzzleID::1A1B]:
            // Do stuff
}

// 

That would let you keep your string approach, while also being fairly performant and flexible as you only take a hit calculating the CRC which for such a short string isn’t a big deal.