Vik*_*ehr 5 c++ template-meta-programming constexpr c++11
考虑以下代码:
#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();
}
};
}
Run Code Online (Sandbox Code Playgroud)
为什么hash0(str0由值创建的地方)在运行时得到评估hash1(在哪里str1通过引用创建)在编译时得到评估?我在MSVC和GCC 6.2/7.0中都尝试过它,看起来它们都失败了.它是否在标准中阻止在编译时对其进行评估?
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;
}
Run Code Online (Sandbox Code Playgroud)
进一步扩展它,我如何强制它在编译时使用constexpr函数进行评估:
auto func1(std::unordered_set<PrehashedString>& iset) {
return iset.count("my_key");
}
Run Code Online (Sandbox Code Playgroud)
注意:
我知道如何通过使构造函数只接受字符串文字(template <size_t N> PrehashedString(const char (&istring)[N]){...}),并利用字符串文字长度作为哈希函数的模板参数来实现这一点,我只是好奇它失败的原因.