3

だから、みんな、私はstd::unordered multimapただの楽しみのために遊んでいます。unsigned short(この例では)カスタム ハッシュと equal を使用して sを保存したいと思います。

面白い部分は何ですか?2 つの項目が両方とも偶数または奇数の場合に等しいこと。

したがって、私が理解している限りでは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;
}

したがって、上記のコードを実行すると、正しい値 3、10、4、23 が見つかります (もちろんこの順序ではありません)。

予期せず、 3呼び出しに一致するf()すべての値を出力すると、3 と 23 の 2 つの答えが得られます。しかし、1000 を要求すると、すべての偶数が出力されると思っていましたが、間違っていました。

size 4
buck 5
# 0 : 4 : 1
# 1 : 10 : 1
# 2 : 3 : 0
# 3 : 23 : 0
there is  : 10 : 1

ここで何か不足していますか?(答えは明らかにイエスです)

4

1 に答える 1

6

あなたがやっていることは未定義の動作です: 等しい要素には等しいハッシュ値が必要です。規格による(強調地雷)

23.2.5 順不同の連想コンテナ [unord.req]

5 タイプ Key の 2 つの値 k1 と k2 は、これらの値が渡されたときにコンテナーのキー等価述語が true を返す場合、同等と見なされます。k1 と k2 が等しい場合、コンテナーのハッシュ関数は両方に対して同じ値を返すものとします

モジュロ 2 に関して同等性を定義するため、渡される整数のモジュロ 2 でハッシュ関数を使用する必要もあります。std::unordered_multimapまた、要素が 2 つ以上ある場合はすぐに必要であることも意味します。

于 2013-07-22T09:23:44.430 に答える