I tried to use std::tuple as an element of std::set where std tuple consists of std::string and a bool (for this example only, in normal use case the tuple consists of 3 elements). The string of the tuple shall be unique, therefore I created comparator that would sort the elements on the first element of the tuple. However, when inserting into aforementioned set I do get duplicate elements in the container. I cannot see where I am making a mistake. Thanks in advance for suggestions!
#include <set>
#include <functional>
#include <iostream>
using namespace std;
int main() {
using tuple_t = std::tuple<std::string, bool>;
std::function<bool(const tuple_t &, const tuple_t &)> tupleCmp =
[](const tuple_t & l, const tuple_t & r) -> bool {
return static_cast<bool>(std::get<0>(l).compare(std::get<0>(r)));
};
set<tuple_t, decltype(tupleCmp)> s(tupleCmp);
s.insert(make_tuple("ahoy", false));
s.insert(make_tuple("this", false));
s.insert(make_tuple("creates", false));
s.insert(make_tuple("duplicates", false));
s.insert(make_tuple("ahoy", false));
for (const auto & i : s){
cout << get<0>(i) << endl;
}
auto debug_stop = 0;
}
Output:
ahoy
duplicates
creates
this
ahoy
std::string::compare
returns int
(neg, 0, positive) not bool
(less than),
you want
std::get<0>(l).compare(std::get<0>(r)) < 0;
or
std::get<0>(l) < std::get<0>(r);
a.compare(b)
returns:
0 when the strings are equal
negative when a comes before b (ie a < b)
positive when b comes before a (ie b < a)
However, the comparators return value is converted to a bool
and anything but 0
is converted to true
, hence your comparator considers a < b
to be true
for any a
and b
unless a == b
. In particular a < b
is true
and b < a
is considered as true
as well. This is not in accordance with the requirement of a strict weak ordering and causes undefined behavior. You can use the "normal" <
to compare the strings.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.