unordered_set 中可以有两个被认为相等的键吗?

Possible to have two keys in an unordered_set, that are considered equal?

From here:

Pred: The unordered_set object uses this expression to determine whether two element keys are equivalent. No two elements in an unordered_set container can have keys that yield true using this predicate.

还有来自 23.5.6.1/1 的:

An unordered_set is an unordered associative container that supports unique keys (an unordered_set contains at most one of each key value) and in which the elements’ keys are the elements themselves. The unordered_set class supports forward iterators.

但如果我定义自己的哈希器和使用 class 类型的不同功能的等效操作,我可以绕过它。

#include <iostream>
#include <unordered_set> //for unordered_set and unordered_multiset

using namespace std;

struct A{
    A() = default;
    A(int a, int b): x(a), y(b) {}
    int x = 0, y = 0;

};

size_t hasher(const A &sd){
    return hash<int>()(sd.x);
}

bool eqOp(const A &lhs, const A &rhs){
    return lhs.y == rhs.y;
}


int main(){

    unordered_set<A, decltype(hasher)*, decltype(eqOp)*> unorderedA(10, hasher, eqOp);

    unorderedA.emplace(2,3);
    unorderedA.emplace(3,3);

    for(const auto& c : unorderedA)
        cout << c.x << " " << c.y << endl;
}

输出;

3 3
2 3

我明白发生了什么:散列器根据它们的 x 值将每个键放在不同的桶中。然而,由于它们的 y 值,我的 eqOp 函数应该认为这两个键是相等的,但由于它们被放置在不同的存储桶中,因此永远不会检查它们是否相等。那么一个无序的容器可以包含两个等价的key只要进入不同的bucket是不是正常的功能。还是编码员有责任确保编写哈希器和谓词以将等效键放在同一个桶中?或者我的 eqOp 函数是否违反了编译器未检测到的规则?

在集合和映射中很清楚:提供给它们的谓词定义了严格的弱排序,因此被认为等价的两个键只有一个与之关联的元素。在无序映射中,我不太清楚:两个等效的键可以有不同的元素与之关联,只要这些键位于不同的桶中。但是上面的那些消息来源感觉他们告诉我的不是这样。

不,这是不可能的。您的示例无效,因为标准要求您 return 等效键的相同哈希值:

23.2.5 Unordered associative containers

  1. Two values k1 and k2 of type Key are considered equivalent if the container’s key_equal function object returns true when passed those values. If k1 and k2 are equivalent, the hash function shall return the same value for both. [ Note: Thus, when an unordered associative container is instantiated with a non-default Pred parameter it usually needs a non-default Hash parameter as well. — end note ]

图书馆用户无论如何都无法确保值落入不同的桶中,因为没有定义所有可能的哈希值如何整体映射到桶索引或映射上的操作如何改变桶的数量。