【问题标题】:C++11 Hash function for any enum type任何枚举类型的 C++11 哈希函数
【发布时间】:2012-03-10 12:08:37
【问题描述】:
我正在为我的对象编写一个哈希函数。感谢Generic Hash function for all STL-containers,我已经可以散列容器并组合散列。但我的课程也有枚举。当然,我可以为每个枚举创建一个哈希函数,但这似乎不是一个好主意。是否可以为std::hash 创建一些通用规范,以便将其应用于每个枚举?类似的东西,使用std::enable_if 和std::is_enum
namespace std {
template <class E>
class hash<typename std::enable_if<std::is_enum<E>::value, E>::type> {
public:
size_t operator()( const E& e ) const {
return std::hash<std::underlying_type<E>::type>()( e );
}
};
};
PS。此代码无法编译
error: template parameters not used in partial specialization:
error: ‘E’
【问题讨论】:
标签:
c++
templates
enums
c++11
hash-function
【解决方案1】:
您的E 参数无法推导出来,因为编译器无法知道您的enable_if<...>::type 最终再次表示E(事实上,它的一些专业化设计不这样做!) .对于E,它被称为“非推断上下文”。
如果hash 只有一个参数,就没有办法(据我所知)SFINAE 排除您的部分专业化。
【解决方案2】:
如果您愿意使用宏,您可以在枚举声明旁边转储正确的 std::hash 特化。
否则,我发现轻松散列枚举值的唯一方法是概括散列类型:
struct enum_hash
{
template <typename T>
inline
typename std::enable_if<std::is_enum<T>::value, std::size_t>::type
operator ()(T const value) const
{
return static_cast<std::size_t>(value);
}
};
并以这种方式使用它:
enum class E { a, b, c };
std::unordered_map<E, std:string, enum_hash> map;
map[E::a] = "a";
【解决方案3】:
标准禁止您尝试做的事情。
[命名空间.std]
如果 C++ 程序添加声明或
对命名空间 std 或命名空间 std 内的命名空间的定义
除非另有说明。
程序可以为任何
标准库模板到命名空间 std 仅当声明
取决于用户定义的类型,并且专业化满足
原始模板的标准库要求,而不是
明确禁止。
因此,您当然可以在这些答案中追求一些想法,但不能将其称为 std::hash。定义自己的“enum_hash”模板似乎是个好主意。