Is it possible to use FName for a switch in C++?

If so, how do you call it? At the moment I’m trying;

switch (MyObject->MyFName.GetNumber())
{
case FNameToCheck.GetNumber():
{}
}

No dice.

Thanks!!

Hi Robbie,

No, C++ does not have allow a mechanism for ‘overloading switch’ for your own types and, even then, case statements cannot use runtime values.

Steve

I’m getting two errors on the case FName, depending on what I do.

“this” cannot be used in a constant expression
or
expression must have a constant value

(forcing int32 does that)

Does it work if you force them as integers before hand? Seems strange why it wouldn’t as GetNumber() returns an int32 anyway.

int32 aNum = MyObject->MyFName.GetNumber();
int32 numCheck = FNameToCheck.GetNumber();
switch (aNum)
{
case numCheck:
{}
}

ok thanks Steve

I surprised UE4 doesn’t already have this, considering all the pre-gen steps that already exist - but if you need to roll this yourself, try creating a macro that uses the same crc value.

code would look like:

switch(name.GetNumber())
{
case FNAME_AS_NUMBER("MyString0", 0x0):
case FNAME_AS_NUMBER("MyString1", 0x0):
...
}

The macro itself would compile out to just the constant number to make the valid switch statement. Use a separate tool that parses the file for the above macro, and replaces the number with the crc calculation based on the FName’s own crc code (they would obviously need to be the same number).

You can choose to run the tool every compile, on demand (ie during new development), as a pre-checkin script, etc.

This could be useful for other situations than just switch statements, too.

This would add an undesirable amount of time to build iteration times.

There is a proposal for compile-time string processing in C++ (and would thus allow the compiler to generate hashes from string literals), and is available on Clang and GCC, but not Visual Studio, so we would be unable to provide such a feature as a general solution.

However, we are unlikely to provide such a feature anyway. CRCs are not unique, so this would result in highly confusing compiler errors when two FNames coincidentally hash to the same value.

Steve

I agree that the every-build processing would add a lot of extra time if it were a serial task, since it would have to hit practically every compiled file. That is the reason we’ve always gone with the other suggestion of running the tool during development only, then as a pre check-in script to make sure nothing is forgotten.
Daily builds running a verifier script (in case the algorithm changes, or someone got around the scripts somehow) helps, too.

In other engines, I’ve either used a 64bit hash, or use a crc32 algorithm that is extremely unlikely to collide, then build in (non-runtime) string databases and warnings when a collision does occur. It’s usually totally within reason to change one of the strings slightly to avoid the collision, and that can help simplify the runtime logic if that assumption is allowed and enforced.

I’m not going to hold my breath on the added language features. As usual, it’s always lowest common denominator, and with consoles, even gen3 didn’t support c++11. As it is, there are c++11 features that aren’t implemented in vs2013, which is what UE4 recommends, so I’m not optimistic that we’ll get to features that haven’t even gotten past the proposal stage yet - at least any time soon.