C++ unordered_map使用自定义键类型
unordered_map定义(C++11)
template<
class Key,
class T,
class Hash = std::hash<Key>,
class KeyEqual = std::equal_to<Key>,
class Allocator = std::allocator< std::pair<const Key, T> >
> class unordered_map; Key代表键值(key),T是根据哈希函数得到的值(value),Hash是哈希函数的函数对象,KeyEqual是等比函数的函数对象,通过"=="来判断两个key是否相等。想使用自定义的键类型,必须实现hash函数和等比函数。
实现
- 法一:利用std::function中的默认hash函数std::hash
#include <functional>
#include <unordered_map>
class mypair
{
public:
char first;
char second;
mypair(char a, char b)
{
if( a < b)
{
first = a;
second = b;
}
else
{
first = b;
second = a;
}
}
bool operator==(const mypair& rhs)
{
return rhs.first == this->first && rhs.second == this->second;
}
};
static size_t mypair_hash(const mypair& tmp)
{
return hash<char>()(tmp.first) ^ hash<char>()(tmp.second);
}
int main()
{
//ERRO: unordered_map<mypair, int, decltype(&mypair_hash)> ids;
//ERRO: unordered_map<mypair, int, mypair_hash> ids(100, mypair_hash );
//OK: unordered_map<mypair, int, decltype(&mypair_hash)> ids(100, mypair_hash );
unordered_map<mypair, int, decltype(&mypair_hash)> memo(20/*, mypair_hash*/); //在这里decltype后面必须要使用引用
/*
* code
*/
} Note:
1) decltype(exp)推导的内容如果是一个左值,那么 decltype(exp) 的类型就是 exp 的引用。在这里mypair_hash是一个函数,如果是自动推导得到的是函数的返回值,不是引用类型,运行时编译器会报错,在hashtable_policy.h中:field 'std::__detail::_Hashtable_ebo_helper<1, long long unsigned int(const mypair&), false>::_M_tp' invalidly declared function type
2) 参考的博客中说memo初始化时必须传入mypair_hash构造函数,但是我尝试不传入发现也是可以编译通过和运行的。
- 法二:重载operator()类,打包哈希函数变成函数对象
class mypair
{
public:
char first;
char second;
mypair(const char& a, const char& b)
{
first = a;
second = b;
}
bool operator==(const mypair& rhs) const
{
return rhs.first == first && rhs.second == second;
}
};
struct hashname
{
size_t operator()(const mypair& tmp) const
{
return (hash<char>()(tmp.first)) ^ (hash<char>()(tmp.second));
}
};
int main()
{
unordered_map<mypair, int, hashname> memo(20);
/*
* code
*/
} 可以直接运行通过,没有什么坑。

查看12道真题和解析