如何在关联容器中使用自定义类型

0.自定义类型需要满足的条件

我们需要为自定义类型Key实现一个Function Object,他需要遵守以下条件:

  1. 返回类型为std::size_t
  2. 接受单个参数,参数类型为Key,一般我会习惯使用const Key& key
  3. 他是一个常量成员函数
  4. 他不会抛出异常
  5. 对于相同的Key,我们需要返回相同的值;对于不同的Key,我们需要尽量减小collision的发生

听上去很多要求,其实很简单,我们有两种方法来实现以上要求,下面一一阐述。

1.std::hash的template specialization

我们选择std::pair作为哈希表的Key

namespace std{
    template <>
    struct hash>{
        std::size_t operator()(const std::pair& p)const noexcept {
            return std::hash()(p.first)^std::hash()(p.second);
        }
    };
}

接下来我们就可以直接使用了

class UserDefinedHash{
public:
    UserDefinedHash(){
    }
    void addData(const std::pair& key,int val){
        templateSpecilization[key]=val;
    }
    int showData(const std::pair& key){
        auto re=templateSpecilization.find(key);
        if(re != templateSpecilization.end())
            return templateSpecilization.at(key);
        return -1;
    }

private:
    std::unordered_map,int> templateSpecilization;
};

2.使用自定义Function Object

struct MyHash{
    std::size_t operator()(const std::pair& p) const noexcept {
        return std::hash()(p.first)^std::hash()(p.second);
    }
};

在使用时,制定std::unordered_map的第三个参数为MyHash即可

class UserDefinedHash{
public:
    UserDefinedHash(){
    }
    void addData(const std::pair& key,int val){
        functor[key]=val;
    }
private:
    std::unordered_map,int,MyHash> functor;
};

3.其他的思考

在选择哈希函数时,上面第二个例子其实并不好,因为当Key{1,1}{n,n}时,返回的哈希经过XOR运算,结果都是一样的,所以我们在选择哈希函数时最好慎重考虑,避免一些明显的错误,如果有条件可以使用boost::hash_combine.

你可能感兴趣的:(如何在关联容器中使用自定义类型)