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:
Avi Kivity
2015-03-01 13:32:34 +02:00
parent 1e5df06f9a
commit 25168fc73d

View File

@@ -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));
}
};