【发布时间】:2019-06-06 21:31:34
【问题描述】:
我最近在 ETT 图书馆遇到了一个有趣的课程。此类用于计算字符串的哈希值,如下所示:
std::uint32_t hashVal = hashed_string::to_value("ABC");
hashed_string hs{"ABC"};
std::uint32_t hashVal2 = hs.value();
在查看此类的实现时,我注意到没有一个构造函数或hashed_string::to_value 成员函数直接采用const char*。相反,他们采用了一个名为const_wrapper 的简单结构。下面是该类实现的简化视图来说明这一点:
/*
A hashed string is a compile-time tool that allows users to use
human-readable identifers in the codebase while using their numeric
counterparts at runtime
*/
class hashed_string
{
private:
struct const_wrapper
{
// non-explicit constructor on purpose
constexpr const_wrapper(const char *curr) noexcept: str{curr} {}
const char *str;
};
inline static constexpr std::uint32_t calculateHash(const char* curr) noexcept
{
// ...
}
public:
/*
Returns directly the numeric representation of a string.
Forcing template resolution avoids implicit conversions. An
human-readable identifier can be anything but a plain, old bunch of
characters.
Example of use:
const auto value = hashed_string::to_value("my.png");
*/
template<std::size_t N>
inline static constexpr std::uint32_t to_value(const char (&str)[N]) noexcept
{
return calculateHash(str);
}
/*
Returns directly the numeric representation of a string.
wrapper parameter helps achieving the purpose by relying on overloading.
*/
inline static std::uint32_t to_value(const_wrapper wrapper) noexcept
{
return calculateHash(wrapper.str);
}
/*
Constructs a hashed string from an array of const chars.
Forcing template resolution avoids implicit conversions. An
human-readable identifier can be anything but a plain, old bunch of
characters.
Example of use:
hashed_string hs{"my.png"};
*/
template<std::size_t N>
constexpr hashed_string(const char (&curr)[N]) noexcept
: str{curr}, hash{calculateHash(curr)}
{}
/*
Explicit constructor on purpose to avoid constructing a hashed
string directly from a `const char *`.
wrapper parameter helps achieving the purpose by relying on overloading.
*/
explicit constexpr hashed_string(const_wrapper wrapper) noexcept
: str{wrapper.str}, hash{calculateHash(wrapper.str)}
{}
//...
private:
const char *str;
std::uint32_t hash;
};
不幸的是,我看不到 const_wrapper 结构的用途。它是否与顶部的注释有关,其中指出“哈希字符串是编译时工具......”?
我也不确定模板函数上方出现的 cmets 是什么意思,即“强制模板解析避免隐式转换”。有人能解释一下吗?
最后,有趣的是要注意这个类是如何被另一个类使用的,该类维护一个以下类型的std::unordered_map:std::unordered_map<hashed_string, Resource>
这个其他类提供了一个成员函数,可以使用键等字符串向地图添加资源。其实现的简化视图如下所示:
bool addResource(hashed_string id, Resource res)
{
// ...
resourceMap[id] = res;
// ...
}
我的问题是:使用 hashed_strings 作为我们地图的键而不是 std::strings 有什么好处?使用 hashed_strings 之类的数字类型是否更有效?
感谢您提供任何信息。学习这门课让我学到了很多东西。
【问题讨论】:
-
在汇编级别的整数比较比字符串的比较快。
标签: c++ hash overload-resolution