我有一个在类中定义的枚举类型,我想创建一个无序的这些对象作为类的成员:
#include <unordered_set> class Foo { public: enum Bar { SOME_VALUE }; // Error: implicit instantiation of std::hash std::unordered_set<Bar> getValues() const { return _values; } private: std::unordered_set<Bar> _values; };
现在,我知道明确的答案是将自定义散列函数添加到unordered_set中:
std::unordered_set<Bar,BarHasher>
但是,我想知道的是,如果有一种方法专门为Bar枚举专用std :: hash,那么使用unordered_map的任何人都会自动获取散列行为.
这与所有其他数据类型,但不是枚举 – 因为枚举不能被转发声明.
为了这个工作,我必须在枚举定义之后放置std :: hash的定义,但是在第一次使用之前,这意味着我必须将它放在类体中,这样就赢了不工作
解决方法
However,what I’m wondering is if there’s a way to specialize std::hash for the Bar enum so that anyone who uses unordered_map gets the hashing behavior automatically.
@H_404_21@没有奇迹,所以任何人只有在专业化之后才会使用专门的std :: hash.既然你不能专门在另一个类中进行类化,并且枚举是嵌套的,那么在类中使用std :: hash将是有问题的.正如你所指出的枚举不能向前宣称.所以有唯一的解决方案(没有创建基类或“不察觉”枚举)在类中使用专门的std :: hash:通过引用聚合/声明,并在std :: hash专门化之后使用外部.
#include <iostream> #include <unordered_set> #include <memory> struct A { enum E { first,second }; A(); std::unique_ptr< std::unordered_set<E> > s_; //!< Here is }; namespace std { template<> class hash<A::E> { public: std::size_t operator()(A::E const& key) const noexcept { std::cout << "hash< A::E >::operator()" << std::endl; return key; } }; } A::A() : s_(new std::unordered_set<E>) { } int main(void) { A a; a.s_->insert(A::first); std::unordered_set< A::E > s; s.insert(A::second); }打印出来
hash< A::E >::operator()
@H_404_21@
hash< A::E >::operator()所以,在A类之外,所有人都可以使用A :: E与std :: hash以及内部类,我们也使用A :: E与std :: hash.另外,如果您不想通过引用聚合std :: unordered_set,则可以仅实现内部使用的自定义哈希值(然后转发std ::哈希调用).