在c++中,是不能用字符串来作为case的标签的,但幸运的是,c++11引入了constexpr和自定义文字常量,将这两个新特性结合,我们实现出看上去像下面这样的代码:
1 2 3 4 5 6 7 8 9 10
| string clss = "xxx"; switch (shash_(clss.c_str())) { case hash_compile_time("Host"): break; case "Sink"_shash: break; case "Switch"_shash: break; }
|
实现方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| typedef unsigned long long hash_t;
constexpr hash_t prime = 0x100000001B3ull; constexpr hash_t basis = 0xCBF29CE484222325ull;
hash_t shash_(char const *str) { hash_t ret{basis};
while (*str) { ret ^= *str; ret *= prime; str++; }
return ret; }
constexpr hash_t hash_compile_time(char const *str, hash_t last_value = basis) { return *str ? hash_compile_time(str + 1, (*str ^ last_value) * prime) : last_value; }
constexpr unsigned long long operator"" _shash(char const *p, size_t) { return hash_compile_time(p); }
|
hash_compile_time
函数只有短短的一行,利用递归得到了与上面shash_
函数得到的同样值,由于用constexpr声明了函数,因此编译器可以在编译期得出一个字符串的hash值,而这正是关键,既然是编译器就可以得到的整型常量,自然可以放到switch的case标签处了。
转自:https://blog.csdn.net/yozidream/article/details/22789147