Vya*_*sky 0 c++ enums gcc c++11 stdhash
I'm not a pro in C++ but somehow I provided a solution while porting my MSVS 2015 C++ code to MinGW 4.9.2 to specialize std::hash class to support all enums. It there's any C++ compiler developers or C++ pro programmers here, can you explain why this specialization works, although it is Undefined Behavior according the C++ standard they say?
Link for full code with samples on Gist
#include <unordered_set>
#include <functional>
#if (defined __GNUC__) && (__GNUC__ < 6)
// Adds support of std::hash<enum T> to libstdc++.
// GCC 6 provides it out of the box.
namespace std {
template<typename T>
struct hash {
constexpr size_t operator()(typename std::enable_if<std::is_enum<T>::value, T>::type s) const noexcept {
return static_cast<size_t>(s);
}
};
}
#endif
Run Code Online (Sandbox Code Playgroud)
提供对的支持std::hash<enum T>意味着所有类似的类std::unordered_XXX都将支持任何一个enum作为键。
具有此std::hash定义的GCC 6.1.0 因错误而失败
error: redefinition of 'struct std::hash<_Tp>'
Run Code Online (Sandbox Code Playgroud)
没有此std::hash定义的GCC 5.3.0 对于std :: unordered_set失败,出现以下错误:
In file included from /usr/local/gcc-5.3.0/include/c++/5.3.0/bits/hashtable.h:35:0,
from /usr/local/gcc-5.3.0/include/c++/5.3.0/unordered_set:47,
from prog.cc:1:
/usr/local/gcc-5.3.0/include/c++/5.3.0/bits/hashtable_policy.h: In instantiation of 'struct std::__detail::__is_noexcept_hash<Foo, std::hash<Foo> >':
/usr/local/gcc-5.3.0/include/c++/5.3.0/type_traits:137:12: required from 'struct std::__and_<std::__is_fast_hash<std::hash<Foo> >, std::__detail::__is_noexcept_hash<Foo, std::hash<Foo> > >'
/usr/local/gcc-5.3.0/include/c++/5.3.0/type_traits:148:38: required from 'struct std::__not_<std::__and_<std::__is_fast_hash<std::hash<Foo> >, std::__detail::__is_noexcept_hash<Foo, std::hash<Foo> > > >'
/usr/local/gcc-5.3.0/include/c++/5.3.0/bits/unordered_set.h:95:63: required from 'class std::unordered_set<Foo>'
prog.cc:25:25: required from here
/usr/local/gcc-5.3.0/include/c++/5.3.0/bits/hashtable_policy.h:85:34: error: no match for call to '(const std::hash<Foo>) (const Foo&)'
noexcept(declval<const _Hash&>()(declval<const _Key&>()))>
^
In file included from /usr/local/gcc-5.3.0/include/c++/5.3.0/bits/move.h:57:0,
from /usr/local/gcc-5.3.0/include/c++/5.3.0/bits/stl_pair.h:59,
from /usr/local/gcc-5.3.0/include/c++/5.3.0/utility:70,
from /usr/local/gcc-5.3.0/include/c++/5.3.0/unordered_set:38,
from prog.cc:1:
/usr/local/gcc-5.3.0/include/c++/5.3.0/type_traits: In instantiation of 'struct std::__not_<std::__and_<std::__is_fast_hash<std::hash<Foo> >, std::__detail::__is_noexcept_hash<Foo, std::hash<Foo> > > >':
/usr/local/gcc-5.3.0/include/c++/5.3.0/bits/unordered_set.h:95:63: required from 'class std::unordered_set<Foo>'
prog.cc:25:25: required from here
/usr/local/gcc-5.3.0/include/c++/5.3.0/type_traits:148:38: error: 'value' is not a member of 'std::__and_<std::__is_fast_hash<std::hash<Foo> >, std::__detail::__is_noexcept_hash<Foo, std::hash<Foo> > >'
: public integral_constant<bool, !_Pp::value>
...
Run Code Online (Sandbox Code Playgroud)
这是一个格式错误的程序,不需要进行诊断,因为不允许为模板类型提供基本的专业知识std。
之所以起作用,是因为在某些实现中,提供这种基本专业化的目的是将所有内容 重定向,std::hash<T>而无需将显式专业化到您的哈希实现。然后,您的operator()收益只能与enums一起使用,但这不是它起作用的原因,也不能防止它使程序在不需要诊断的情况下不正确。
实际上,它可能是因为有人在SFINAE中启用std::hash了gcc 6.1中的空基本实现而失败了:不确定,这可能是某些C ++标准强制要求的,但是如果不能,这是实现改进的质量。
正确的方法是创建
struct enum_hash {
template<typename T>
constexpr
typename std::enable_if<std::is_enum<T>::value,std::size_t>::type
operator()(T s) const noexcept {
return static_cast<std::size_t>(s);
}
};
Run Code Online (Sandbox Code Playgroud)
可以散列任何枚举的类型。
现在,通过,enum_hash以unordered_set<some_enum, enum_hash>这样的。
| 归档时间: |
|
| 查看次数: |
411 次 |
| 最近记录: |