為什么還有一個關于字串到哈希轉換的問題
我的問題與流行的如何將 std::string 轉換為 const char* 或 char*問題基本相同,但有所不同。我在編譯時需要哈希。在拒絕我的問題之前,讓我簡要解釋一下我的動機。
動機
在我正在構建的框架中,我有很多執行緒。我精心設計了檔案結構,以便這些執行緒重用功能相同的檔案,以免違反 ODR 并失去可維護性。串列頂部是錯誤日志記錄。我精心設計的代碼請求在這些不同的應用程式中按原樣重復使用。所以初始化的errorLogger物件需要是每個執行緒的不同實體。
建議的解決方案
使用常量非型別引數模板化我的ErrorLogger類。在我的框架中,每個應用程式都有一個唯一的字串來標識自己。現在,如果我可以在編譯時散列該字串,我將擁有編譯器生成單獨實體所需的非型別模板引數。
這是不起作用的示例代碼:
#include <string>
std::string threadUniqueStr { "threadUniqueName" };
/*constexpr*/ auto threadUniqueHash = std::hash< std::string > {} ( threadUniqueStr ); // uncommented constexpr results in 'expression did not evaluate to a constant'
template< size_t >
void Func()
{}
int main()
{
//Func< threadUniqueHash >(); // ERROR: expression did not evaluate to a constant
Func< 33 >(); // works fine
}
但也許我忽略了一種更簡單的 C 方法來做到這一點?
編輯 1:我的解決方案
答案 2 顯示了如何使用 string_view 從字串創建哈希,它遵循@NathanOliver 的建議,即您必須撰寫自己的哈希函式才能使其成為 constexpr。但我知道撰寫自己的哈希函式可能會出現問題。@Pepijn Kramer 指出 1)兩個字串可能仍會產生相同的哈希值,以及 2)根據他的經驗,在頂部具有應用程式報告和單個錯誤報告行為派生類的類層次結構在多開發情況下(如我的)服務于他的目的)。由于我不想以未經嘗試的方式使用模板非型別引數功能,即使我可以為此提供案例,我將創建自己的ErrorLogger類層次結構。感謝大家的幫助。
uj5u.com熱心網友回復:
在 C 17 中,astring_view可以是 constexpr,因此您可以制作自己的散列函式,該函式采用其中之一,例如此處某人的答案中的散列函式如下所示。
#include <string_view>
#include <iostream>
constexpr size_t some_hash(std::string_view sv) {
size_t hash = 5381;
for (auto c : sv)
hash = ((hash << 5) hash) c;
return hash;
}
template<size_t N>
void some_function() {
std::cout << N << "\n";
}
int main() {
some_function<some_hash("foobar")>();
}
uj5u.com熱心網友回復:
問題的本質是這樣的:
template并且constexpr需要在編譯時進行評估,std::hash在運行時計算并且在編譯器外部。
您可以說散列的結果是 const,但您似乎想告訴編譯器運行某個函式。編譯器通常不這樣做。
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/524444.html
上一篇:Haskell“解碼”
