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
     */
}

可以直接运行通过,没有什么坑。