使用unordered_multimap

sen*_*iwa 3 c++ unordered-map hashmap c++11

所以,伙计们,我std::unordered multimap只是为了好玩而玩.我想存储(在这个例子中)unsigned shorts,使用自定义哈希并且相等.

有趣的是什么?如果它们是偶数或奇数,则两个项目相等.

所以,据我所知,我不能使用std::unordered_map,即使实际值不同:自定义谓词另有说法.(如果我错了,请纠正我,显然!)

所以回顾一下:我存储不同的整数,因此存储不同的哈希值,但它们在谓词下的值可能是相同的.

#include <iostream>
#include <unordered_map>

class tt
{
public:

    tt(const unsigned short v = 0) : i(v) { };

    unsigned short i;
};

class tt_hash
{
public:
    size_t operator()(const tt &v) const
    {
        auto f = std::hash<unsigned short>();
        return f(v.i);
    };
};

class tt_equal
{
public:
    bool operator()(const tt &u, const tt &v) const
    {
        return (u.i % 2) == (v.i % 2);
    };
};

typedef std::unordered_multimap<tt, bool, tt_hash, tt_equal> mymap;

// Print all values that match a criteria
void f(const mymap &m, unsigned short c)
{
    auto range = m.equal_range(c);

    auto target = range.first;

    if (target == m.end())
    {
        std::cout << "not found : " << (int) c << std::endl;
    }
    else
    {
        for (auto i = target; i != range.second; i++)
            std::cout << "there is  : " << (int) i->first.i << " : " << i->second << std::endl;
    }

}

int main(int argc, const char * argv[])
{    
    mymap m;

    m.emplace(std::make_pair(tt(3), false));
    m.emplace(std::make_pair(tt(10), true));
    m.emplace(std::make_pair(tt(4), true));
    m.emplace(std::make_pair(tt(23), false));

    std::cout << "size " << m.size() << std::endl;
    std::cout << "buck " << m.bucket_count() << std::endl;

    int c = 0;

    for (auto i = m.begin(); i != m.end(); i++)
        std::cout << "# " << c++ << " : " << (int) i->first.i << " : " << i->second << std::endl;

    f(m, 3);

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

所以,当我执行上面的代码时,我找到了正确的值,3,10,4,23(当然不是按此顺序).

出乎意料的是,当打印所有匹配3个呼叫的值时f(),我得到两个答案,3和23; 但是当我要求1000时,我希望打印所有偶数,但我错了:

size 4
buck 5
# 0 : 4 : 1
# 1 : 10 : 1
# 2 : 3 : 0
# 3 : 23 : 0
there is  : 10 : 1
Run Code Online (Sandbox Code Playgroud)

我在这里错过了什么吗?(答案显然是肯定的)

Tem*_*Rex 6

你正在做的是未定义的行为:相等的元素应具有相等的哈希值.根据标准(强调我的)

23.2.5无序关联容器[unord.req]

5如果容器的键等式谓词在传递这些值时返回true,则认为Key类型的两个值k1和k2是等效的.如果k1和k2是等价的,则容器的散列函数应为两者返回相同的值.

由于您使用模2定义了等价,因此您还需要在传递的整数的模2上使用散列函数.这也意味着std::unordered_multimap只要有2个以上的元素就需要它.