作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有代表图像名称的字符串,如“foobar.png”等。如您所知,C++ 中的 switch-case 不支持在字符串上切换。
我正在尝试解决这个问题,方法是将字符串散列为 std::size_t,然后在 switch-case 语句中使用该值。
例如:
//frameName is an std::string which represents foobar.png etc..
switch (shs(frameName)) { //shs is my hash func which returns std::size_t;
case shs(Pfn::fs1x1): //Problem in this line
default:{
break;
}
}
在单独的文件 (Pfn.hpp) 中:
命名空间 Pfn{ const std::string fs1x1 = "fs1x1";};
问题是,在我的 case 语句中,编译器报告 shs(Pfn::fs1x1)
不是常量表达式。确切的错误信息是:
Case value is not a constant expression:
预先计算出所有哈希值然后将它们硬编码到 case 语句中真的很乏味。您对我如何在运行时以某种方式创建常量表达式有什么建议吗?
编辑:我的 shs 函数:
static std::size_t shs(std::string string){
return Hash::shs::hs(string);
}
//...
namespace Hash{
struct shs{
public:
inline std::size_t operator()(const std::string &string)const{
return hashString(string);
}
static std::size_t hs(const std::string &string){
std::size_t seed = 0;
hash_combine(seed,string);
return seed;
}
//From Boost::hash_combine.
template <class T>
static inline void hash_combine(std::size_t& seed, const T& v)
{
std::hash<T> hasher;
seed ^= hasher(v) + 0x9e3779b9 + (seed<<6) + (seed>>2);
};
};
}
最佳答案
shs
的参数需要是 constexpr
并且 shs
本身也必须是 constexpr
。由于 C++11 对 constexpr 函数的限制,您可能希望为哈希的编译时版本和运行时版本提供不同的实现。
我wrote前段时间关于这个主题的帖子,使用fnv1a作为哈希算法。以下是重要部分:
常量:
typedef std::uint64_t hash_t;
constexpr hash_t prime = 0x100000001B3ull;
constexpr hash_t basis = 0xCBF29CE484222325ull;
运行时哈希:
hash_t hash(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 "" _hash(char const* p, size_t)
{
return hash_compile_time(p);
}
和用法:
switch(fnv1a_64::hash(str)){
case "first"_hash:
cout << "1st one" << endl;
break;
case "second"_hash:
cout << "2nd one" << endl;
break;
case "third"_hash:
cout << "3rd one" << endl;
break;
default:
cout << "Default..." << endl;
}
但是,请为 child 着想!除非您可以保证不会发生哈希冲突,否则这是在玩火,不适合作为生产代码。
关于c++ - 如何将字符串转换为常量整数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40713061/
我是一名优秀的程序员,十分优秀!