0
\$\begingroup\$

I'm making XML parsing code with FXmlNode. I want to iterate through GetChildrenNodes(), and use switch-case with FString which is return value of FXmlNode::GetTag(). Is there someway to do that? Or should I use

 if (Tag == TEXT("XX") .. else if (Tag == TEXT("YY"));

Thanks.

\$\endgroup\$
  • \$\begingroup\$ switch cases in c++ only support primatives (ints, chars, etc) stackoverflow.com/questions/650162/… \$\endgroup\$ – CobaltHex Sep 12 '17 at 6:31
  • \$\begingroup\$ @CobaltHex That's right. I wander if I can get some kind of hash value from FString. \$\endgroup\$ – P-P Sep 12 '17 at 10:20
3
\$\begingroup\$

In C++, you can't switch on strings, only integers (and the values you compare to must be constant).

But it is possible to indirectly switch on strings by choosing a stable mapping from string to integer (such as a hash function), applying that to the constants as well as the string to switch on, and using that. Because the expression in a case statement must be a compile-time constant, you're likely going to want to write that hash or mapping yourself and not rely on anything Unreal provides, as it may not be sufficient for this purpose.

FNV1a is a simple, decent hash function, and can be implemented as a constexpr function in C++. This will let you write:

constexpr std::uint32_t fnv1a(const char* s) { ... };

...

switch(fnv1a(someString)) {
  case fnv1a("Foo"): ... break;
  case fnv1a("Bar"): ... break;
  default: ... break;
}

If you don't have a modern C++ compiler, you will be forced to manually hash the strings yourself and write the resulting constant values in the case statements, which is exceedingly cumbersome.

Frankly, I'd argue that if the comparison code in question isn't a performance bottleneck, you're better off not overcomplicating things and just doing if/else chains. If it is a performance bottleneck, it might be worth revisiting whether or not you can replace the strings in a broader, algorithmic sense as it will likely be a bigger performance win.

As always, your mileage may vary, and you'll want to engage the services of a profiler to ensure you're actually gaining something by adding this extra layer of indirection.

\$\endgroup\$
  • \$\begingroup\$ Perhaps use an enum instead? If you are using XML, your set of strings should be known and well-formed, right? \$\endgroup\$ – JonS Sep 13 '17 at 2:38

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.