enum: fix std::hash<> non-specialization for enum types
SFINAE only works for substituted template parameters, not any complication error (or it would be called CEINAE); therefore hash<T> for enums will fail to compile, given a non-enum, rather than being ignored. It's not possible to specialize hash<> for enums, since the primary template does not have en extra Enable template argument for use with enable_if. We therefore rename it to enum_hash<> and require users to explicitly define hash<MyEnum> as inheriting from it.
This commit is contained in:
25
core/enum.hh
25
core/enum.hh
@@ -22,24 +22,21 @@
|
||||
#pragma once
|
||||
|
||||
/*
|
||||
* This header file defines a hash function for all enum types, using the
|
||||
* This header file defines a hash function for enum types, using the
|
||||
* standard hash function of the underlying type (such as int). This makes
|
||||
* it possible to use an enum type as a key for std::unordered_map, for
|
||||
* example.
|
||||
* it possible to inherit from this type to
|
||||
*/
|
||||
|
||||
#include <type_traits>
|
||||
#include <functional>
|
||||
#include <cstddef>
|
||||
|
||||
namespace std {
|
||||
template<typename T>
|
||||
class hash {
|
||||
using sfinae = typename std::enable_if<std::is_enum<T>::value, T>::type;
|
||||
public:
|
||||
std::size_t operator()(const T& e) const {
|
||||
using utype = typename std::underlying_type<T>::type;
|
||||
return std::hash<utype>()(static_cast<utype>(e));
|
||||
}
|
||||
};
|
||||
}
|
||||
template <typename T>
|
||||
class enum_hash {
|
||||
static_assert(std::is_enum<T>::value, "must be an enum");
|
||||
public:
|
||||
std::size_t operator()(const T& e) const {
|
||||
using utype = typename std::underlying_type<T>::type;
|
||||
return std::hash<utype>()(static_cast<utype>(e));
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user