Reputation: 91
In C++ by default both std::set
and std::multiset
have std::less<T>
as their comparator. Can anyone please explain how does std::multiset
allow duplicates and std::set
does not?
Upvotes: 7
Views: 5018
Reputation: 56577
To follow up on Jerry's answer, note that std::set
and std::multiset
assume that the elements are comparable via a strict weak ordering by operator<
. In particular, the elements do not have to be comparable under operator==
. std::set
only allows non-equivalent elements, whereas std::multiset
allows in addition equivalent elements. This is slightly different from equality/non-equality. Two elements A
and B
are equivalent whenever !(A < B) && !(B < A)
, and it is this latter condition that is checked by std::set::insert
, and if true, the element is not inserted.
Example Live on Ideone
#include <iostream>
#include <set>
struct Foo
{
int _x, _y, _z;
Foo(int x, int y, int z): _x(x), _y(y), _z(z) {}
bool operator<(const Foo& rhs) const // weak majorization
{
return (_x < rhs._x) && (_x + _y < rhs._x + rhs._y) &&
(_x + _y + _z < rhs._x + rhs._y + rhs._z) ;
}
};
int main()
{
std::set<Foo> setFoo;
// try to insert 2 equivalent elements
setFoo.insert(Foo{1, 2, 3});
if(setFoo.insert(Foo{1, 2, 0}).second == false) // failed to insert
std::cout << "Equivalent element already in the set!" << std::endl;
}
Upvotes: 4
Reputation: 490728
Both start with the equivalent an upper_bound
on the existing contents to find the correct insertion point for the new item.
std::set
then checks whether that found an existing item with a key equal to the new key, and if so returns, signaling failure.
std::multiset
just inserts the new item at that point (and if it didn't return in the step above, std::set
does the same).
Upvotes: 7