there are a number of string comparisons. What if you could just send it through a switch?
Yes, sort of ugly, but it works. (If C++11 constexpr were allowed, it could be much more beautiful
.) I constructed the following macro/template hacks for some other project, and thought they might be useful here. However, I do not currently have time to test integrating it myself.
Is it actually faster? I have no idea...
/* helper, truncate to 20 args */
#define _GET_20_ARGS( \
_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, \
... ) \
_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19
/* results in up to 20 arguments, padded with null characters
* requires at least 1 argument */
#define GET_20_ARGS(...) \
_GET_20_ARGS( __VA_ARGS__, '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', \
'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0' )
/* user interface */
#define ID(...) CompileStrHasher<GET_20_ARGS(__VA_ARGS__)>::value
/* hash function (FNV in reverse) */
template< char _0, char _1, char _2, char _3, char _4, char _5, char _6, char _7, char _8, char _9,
char _10, char _11, char _12, char _13, char _14, char _15, char _16, char _17, char _18, char _19 >
struct CompileStrHasher
{
enum
{
value = (_0 ^ ID(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19)) * 16777619u
};
};
/* seed value */
template<>
struct CompileStrHasher<GET_20_ARGS('\0')>
{
enum
{
value = 2166136261u
};
};
// example usage
#if __cplusplus < 201103L
// flat solution (run-time execution)
unsigned HashStr(const char* str)
{
unsigned value = 2166136261u;
if (!*str)
return value;
const char* end = str;
for (int i = 0; *(end + 1) && i < 20; ++end, ++i)
;
do
{
value = (*end ^ value) * 16777619u;
} while (str != (end--));
return value;
}
#else
// recursive C++11 constexpr (compile-time execution)
constexpr unsigned HashStr(const char* str, int depth = 0)
{
return (*str && depth < 20) ? (*str ^ HashStr(str+1, depth+1)) * 16777619u : 2166136261u;
}
#endif
int main()
{
switch (HashStr("str"))
{
case ID('s','t','r'):
return 0;
default:
break;
}
return 1;
}