App*_*ell 71 c++ enums map c++11 enum-class
我有一个包含枚举类的类.
class Shader {
public:
enum class Type {
Vertex = GL_VERTEX_SHADER,
Geometry = GL_GEOMETRY_SHADER,
Fragment = GL_FRAGMENT_SHADER
};
//...
Run Code Online (Sandbox Code Playgroud)
然后,当我在另一个类中实现以下代码时......
std::unordered_map<Shader::Type, Shader> shaders;
Run Code Online (Sandbox Code Playgroud)
...我收到编译错误.
...usr/lib/c++/v1/type_traits:770:38:
Implicit instantiation of undefined template 'std::__1::hash<Shader::Type>'
Run Code Online (Sandbox Code Playgroud)
导致错误的原因是什么?
Dan*_*iel 110
我使用仿函数对象来计算哈希值enum class
:
struct EnumClassHash
{
template <typename T>
std::size_t operator()(T t) const
{
return static_cast<std::size_t>(t);
}
};
Run Code Online (Sandbox Code Playgroud)
现在您可以将它用作第3个模板参数std::unordered_map
:
enum class MyEnum {};
std::unordered_map<MyEnum, int, EnumClassHash> myMap;
Run Code Online (Sandbox Code Playgroud)
所以你不需要提供专业化std::hash
,模板参数演绎就可以了.此外,您可以使用单词using
并自行unordered_map
使用std::hash
或EnumClassHash
根据Key
类型:
template <typename Key>
using HashType = typename std::conditional<std::is_enum<Key>::value, EnumClassHash, std::hash<Key>>::type;
template <typename Key, typename T>
using MyUnorderedMap = std::unordered_map<Key, T, HashType<Key>>;
Run Code Online (Sandbox Code Playgroud)
现在你可以使用MyUnorderedMap
带有enum class
或另一种类型:
MyUnorderedMap<int, int> myMap2;
MyUnorderedMap<MyEnum, int> myMap3;
Run Code Online (Sandbox Code Playgroud)
从理论上说,HashType
可以使用std::underlying_type
,然后EnumClassHash
就没有必要了.这可能是这样的,但我还没有尝试过:
template <typename Key>
using HashType = typename std::conditional<std::is_enum<Key>::value, std::hash<std::underlying_type<Key>::type>, std::hash<Key>>::type;
Run Code Online (Sandbox Code Playgroud)
如果使用std::underlying_type
作品,可能是一个非常好的标准提案.
Dav*_*one 44
这被认为是标准中的缺陷,并在C++ 14中得到修复:http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2148
但是,从gcc 4.9.3开始,此解决方案尚未在libstdc ++中实现:https://gcc.gnu.org/bugzilla/show_bug.cgi ? id = 60970 .
它在2013年的clang的libc ++中修复:http://lists.cs.uiuc.edu/pipermail/cfe-commits/Week-of-Mon-20130902/087778.html
den*_*nim 21
一个非常简单的解决方案是提供这样的哈希函数对象:
std::unordered_map<Shader::Type, Shader, std::hash<int> > shaders;
Run Code Online (Sandbox Code Playgroud)
这就是枚举键的全部内容,不需要提供std :: hash的特化.
将此添加到定义 MyEnumClass 的标头中:
namespace std {
template <> struct hash<MyEnumClass> {
size_t operator() (const MyEnumClass &t) const { return size_t(t); }
};
}
Run Code Online (Sandbox Code Playgroud)
使用时std::unordered_map
,您知道需要哈希函数.对于内置或STL
类型,有可用的默认值,但不适用于用户定义的默认值.如果你只是需要一张地图,你为什么不试试std::map
?
正如KerrekSB指出的那样,std::hash
如果你想使用它,你需要提供一个特殊化std::unordered_map
,例如:
namespace std
{
template<>
struct hash< ::Shader::Type >
{
typedef ::Shader::Type argument_type;
typedef std::underlying_type< argument_type >::type underlying_type;
typedef std::hash< underlying_type >::result_type result_type;
result_type operator()( const argument_type& arg ) const
{
std::hash< underlying_type > hasher;
return hasher( static_cast< underlying_type >( arg ) );
}
};
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
38062 次 |
最近记录: |