我有一个哈希函数可以采用任何对象类型并哈希它,它在std::hash内部使用.因为std::hash不支持枚举类型,所以我创建了函数的重载,1用于枚举std::underlying_type,1用于其他类型:
template <typename T, typename std::enable_if<std::is_enum<T>::value>::type* = nullptr>
static std::size_t Hash(T const & t)
{
return std::hash<typename std::underlying_type<T>::type>()(t);
}
template <typename T, typename std::enable_if<!std::is_enum<T>::value>::type* = nullptr>
static std::size_t Hash(T const & t)
{
return std::hash<T>()(t);
}
Run Code Online (Sandbox Code Playgroud)
这工作正常.然后我尝试将它全部放入一个函数中std::conditional:
template <typename T>
static std::size_t Hash(T const & t)
{
typedef typename std::conditional<std::is_enum<T>::value, std::hash<typename std::underlying_type<T>::type>, std::hash<T>>::type Hasher;
return Hasher()(t);
}
Run Code Online (Sandbox Code Playgroud)
主要:
enum test
{
TEST = 2
};
int main() {
Hash<test>(TEST);
Hash<int>(5);
std::cin.get();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
然而,这给了我一个错误:
/ usr/include/c ++/5/type_traits:2190:38:错误:'int'不是枚举类型typedef __underlying_type(_Tp)类型;
我确实理解错误,但我不明白为什么,我认为std::conditional会阻止这些编译时错误,因为<int>使用std::hash<T>而不是 std::hash<typename std::underlying_type<T>::type>在编译时.
我在这里做错了什么,有没有办法合并这2个功能?
Tar*_*ama 13
std::underlying_type如果模板参数不是枚举,并且两个分支都std::conditional需要有效,那么问题就是格式不正确.
一种可能性是制作一个safe_underlying_type特征,void如果T不是枚举则只返回:
template <typename T, typename = typename std::is_enum<T>::type>
struct safe_underlying_type {
using type = void;
};
template <typename T>
struct safe_underlying_type<T, std::true_type> {
using type = std::underlying_type_t<T>;
};
Run Code Online (Sandbox Code Playgroud)
或者你可以写一个特征来获得你想要的哈希类型:
template <typename T, typename = typename std::is_enum<T>::type>
struct hash_type {
using type = std::hash<T>;
};
template <typename T>
struct hash_type<T, std::true_type> {
using type = std::hash<std::underlying_type_t<T>>;
};
Run Code Online (Sandbox Code Playgroud)
如果你真的想使用conditional,你需要推迟评估:
template<class T> struct identity { using type = T; };
using Hasher = std::hash<typename std::conditional<std::is_enum<T>::value,
std::underlying_type<T>,
identity<T>>::type::type>;
Run Code Online (Sandbox Code Playgroud)
此外,std::hash自LWG 2148以来,应该原生支持枚举.