用于打开字符串的哈希函数 我试图通过一个散列的帮助来切换C++中的一个字符串。这是我和这段代码之间的私事,所以我不想放弃使用enum,尽管我最终只有8个字符串可以放在开关盒中

用于打开字符串的哈希函数 我试图通过一个散列的帮助来切换C++中的一个字符串。这是我和这段代码之间的私事,所以我不想放弃使用enum,尽管我最终只有8个字符串可以放在开关盒中,c++,hash,C++,Hash,结合我在其他主题上看到的内容,我编写了这个非常简单且不太可靠的函数,但这对于我想要做的已经足够了,因为它不专业 我的职能: constexpr长hashstr(conststring&str,inth=0) { return!str[h]?55:(hashstr(str,h+1)*33)+(unsigned char)str[h]; } 然后我在这个非常简单的主函数中调用它(现在),但它不会编译,告诉我情况是错误的(不是常数)。我不理解这个问题,因为对于我来说,arg中的字符串是一个常量,加上

结合我在其他主题上看到的内容,我编写了这个非常简单且不太可靠的函数,但这对于我想要做的已经足够了,因为它不专业

我的职能:

constexpr长hashstr(conststring&str,inth=0)
{
return!str[h]?55:(hashstr(str,h+1)*33)+(unsigned char)str[h];
}
然后我在这个非常简单的主函数中调用它(现在),但它不会编译,告诉我情况是错误的(不是常数)。我不理解这个问题,因为对于我来说,arg中的字符串是一个常量,加上函数返回一个常量表达式

我的主要意见是:

int main(无效){
字符串teststr;
cout>teststr;
int tt=hashstr(teststr);

cout除非您使用的是c++20
std::string
不是
constepr
,所以不能在
hashstr
中使用

返回的值大于
long
中可表示的值,因为有符号算术溢出是未定义的行为,您的代码不能在
constexpr
中使用

解决这两个问题会产生工作代码:

constexpr unsigned long hashstr (const std::string_view &str, int h=0)
{
    return !str[h] ? 55 : ( hashstr(str, h+1) *33) + (unsigned char)(str[h]);
}
请注意,如果查看编译器输出,它可能会告诉您为什么表达式不是
constexpr
,例如,铿锵打印:

错误:大小写值不是常量表达式
case hashstr(“rosathefloridaturtle”):
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
:22:18:注意:非文字类型“const std::string”(又名“const basic_string”)不能在常量表达式中使用
case hashstr(“rosathefloridaturtle”):
更改为
std::string\u视图
打印:

错误:大小写值不是常量表达式
case hashstr(“rosathefloridaturtle”):
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
:9:47:注意:值97009635813568987014超出“long”类型的可表示值范围
return!str[h]?55:(hashstr(str,h+1)*33)+(unsigned char)str[h];
^
:9:29:注意:在调用“hashstr”(“rosathefloridaturtle”,8)”时
return!str[h]?55:(hashstr(str,h+1)*33)+(unsigned char)str[h];

正如@Alan Birtles所说,
std::string
不是基于当前使用的编译器标准的
constepr
,因此不能这样使用

但一个好消息是,您不需要使用
std::string\u view
!,只需要使用
std::string::c\u str()
并使用char指针来获取哈希值

另外,根据需求,我认为您可能需要使用一种称为自然溢出的技术,该技术在散列中广泛使用(实际上,它是一个模函数,但删除了也代表模最大值的模运算符),但它使用的类型是无符号整数,正如Alan所提到的,有符号溢出可能触发ub。因此,请改用无符号类型

下面是我为这种用法实现的代码

#包括
#包括
使用名称空间std;
使用ull=uint64\u t;
常量表达式hashstr(常量字符*s,大小索引=0){
返回s+index==nullptr | | s[index]='\0'?55:hashstr(s,index+1)*33+(无符号字符)(s[index]);
}
constexpr const char*a=“rosathefloridaturtle”;
int main(){
字符串s;
cout>s;
ull tt=hashstr(s.c_str());

请不要标记垃圾邮件。使用和中的一个,不要忘记鸽子洞原则。“为什么
hashstr(“rosathefloridaturtle”)
不是常量”是一个有效的问题,但是您最终得到的代码通常是不正确的。并且不要描述错误消息。发布准确的错误消息。您的
hashstr
定义也不应该编译(至少在gcc中不应该编译)因为字符串索引不是<代码> CONTXPRP</代码>,所以第二个错误是无关紧要的。您可能会发现和有用。考虑使用OpenSSL库中提供的<代码> LHYStrhash 高效,并尽量减少字符串哈希的冲突(这真的很好)。为什么要使用
const std::string_view&
?@PasserBy没有什么特别的危害,只是从OPs代码复制的。递归传递引用可能比复制string视图更便宜,即使复制string_视图应该便宜假设递归没有优化,因为它是一个简单的类型,传递值将在寄存器中完成,而引用必须在堆栈上传递。我猜两者都是noop,通过值传递可以节省最终的间接寻址。但这一切都不重要,
string\u视图&
读起来像
int*&
,这很奇怪。使用引用会导致clang生成更少的代码,并进行优化sabled:The。我刚刚意识到为什么它如此不稳定:我们传递了一个无关的
h
。而且,使用加法作为散列是一个可怕的坏主意。没有
h
,by值看起来要好得多。