Reputation: 283
Sample code:
std::hash_set<int> hs1; // also i try std::unordered_set<int> - same effect
std::hash_set<int> hs2;
hs1.insert(15);
hs1.insert(20);
hs2.insert(20);
hs2.insert(15);
assert(hs1 == hs2);
hash_set doesn't stores elements in some order defined by hash function... why? Please note that this code works in VS2008 using stdext::hash_set.
Upvotes: 4
Views: 769
Reputation: 283
i ask this question here but give no response =) thanks for your feedback.
i also create some simple console test (just to be sure):
#include <iostream>
#include <hash_set>
int main(int argc, char* argv[])
{
stdext::hash_set<int> hs1, hs2;
hs1.insert(10);
hs1.insert(15);
hs2.insert(15);
hs2.insert(10);
std::cout << ((hs1 == hs2) ? "It works!" : "It NOT works") << std::endl;
return EXIT_SUCCESS;
}
and compile it. using vs2008 command prompt:
cl.exe HashSetTest.cpp /oHashSetTest2008.exe
using vs2010 command prompt:
cl.exe HashSetTest.cpp /oHashSetTest2010.exe
I really see different results =)
Upvotes: 1
Reputation: 355227
It looks like equality comparisons are broken for both hash_set
and unordered_set
in Visual C++ 2010.
I implemented a naive equality function for unordered containers using the language from the standard quoted by Matthieu to verify that it's a bug (just to be sure):
template <typename UnorderedContainer>
bool are_equal(const UnorderedContainer& c1, const UnorderedContainer& c2)
{
typedef typename UnorderedContainer::value_type Element;
typedef typename UnorderedContainer::const_iterator Iterator;
typedef std::pair<Iterator, Iterator> IteratorPair;
if (c1.size() != c2.size())
return false;
for (Iterator it(c1.begin()); it != c1.end(); ++it)
{
IteratorPair er1(c1.equal_range(*it));
IteratorPair er2(c2.equal_range(*it));
if (std::distance(er1.first, er1.second) !=
std::distance(er2.first, er2.second))
return false;
// A totally naive implementation of is_permutation:
std::vector<Element> v1(er1.first, er1.second);
std::vector<Element> v2(er2.first, er2.second);
std::sort(v1.begin(), v1.end());
std::sort(v2.begin(), v2.end());
if (!std::equal(v1.begin(), v1.end(), v2.begin()))
return false;
}
return true;
}
It returns that hs1
and hs2
from your example are equal. (Somebody let me know if you spot a bug in that code; I didn't really test it extensively...)
I'll file a defect report on Microsoft Connect.
Upvotes: 4
Reputation: 300209
Finally found the reference in the final draft at 23.2.5, note 11:
Two unordered containers
a
andb
compare equal ifa.size() == b.size()
and, for every equivalent-key group[Ea1,Ea2)
obtained froma.equal_range(Ea1)
, there exists an equivalent-key group[Eb1,Eb2)
obtained fromb.equal_range(Ea1)
, such thatdistance(Ea1, Ea2) == distance(Eb1, Eb2)
andis_permutation(Ea1, Ea2, Eb1)
returnstrue
.
I would bet hash_set
is now implemented in term of unordered_set
(to begin with), but I still don't understand why in your case it would fail.
The complexity requirement is O(N) in the average case but degenerates to O(N2) in the worst case because of the linear-chaining implementation requirement.
Upvotes: 2