考虑以下代码:
#include <unordered_set>
#include <type_traits>
#include <cstring>
constexpr auto cstring_hash(const char* istring) -> size_t {
return (*istring) == '\0' ?
size_t(0):
(*istring) + cstring_hash(istring + 1);
}
constexpr auto cstring_length(const char* istring) -> size_t {
return (*istring) == '\0' ?
size_t(0):
size_t(1) + cstring_length(istring + 1);
}
class PrehashedString {
public:
constexpr PrehashedString(const char* istring)
: str_(istring)
, hash_(cstring_hash(istring))
, size_(cstring_length(istring)) {
}
constexpr auto& get_hash() const { return hash_; }
auto operator==(const PrehashedString& iother) const {
return
size_ == iother.size_ &&
std::strcmp(str_, iother.str_) == 0;
}
private:
const char* str_;
size_t hash_;
size_t size_;
};
namespace std {
template <>
struct hash<PrehashedString> {
constexpr auto operator()(const PrehashedString& ihashed_string) const -> size_t {
return ihashed_string.get_hash();
}
};
}
为什么hash0
(值创建str0
的位置)在hash1
(其中str1
由auto func0() {
const auto str0 = PrehashedString("my_string_0");
const auto hash0 = str0.get_hash();
const auto& str1 = PrehashedString("my_string_1");
const auto hash1 = str1.get_hash();
return hash0 + hash1;
}
创建时在运行时进行评估 reference )在编译时得到评估?
我已经在 MSVC 和 GCC 6.2 / 7.0 中尝试了它,看起来它们都失败了。它是否在标准中阻止在编译时对其进行评估?
auto func1(std::unordered_set<PrehashedString>& iset) {
return iset.count("my_key");
}
进一步扩展它,如何在编译时强制使用constexpr函数进行评估:
(template <size_t N> PrehashedString(const char (&istring)[N]){...})
注意:
我知道如何通过使构造函数只接受字符串文字''
,并利用字符串文字长度作为哈希函数的模板参数来实现这一点,我只是好奇它失败的原因。