c++ - STL set with custom comparator allows duplicate elements -
the following code simplified example produces problem.
a number of strings (char*) inserted set, many of non-unique. duplicate strings should detected , pointer original inserted should returned; however, doesn't happen , inserted string inserted again if not present.
the resulting set should consist of: "aa", "bb", "cc". output shows set ends with: "bb", "cc", "aa", "bb". changing string first inserted seems change duplicate 'allowed.'
the digit prefix on strings not used, added ensure each string has unique pointer; problem still exist without them.
using default comparator , non-prefixed strings work expected, compares pointers; prefixing strings results in unique pointers , strings inserted.
#include <iostream> #include <set> #include <cstring> using std::cout; using std::endl; using std::set; using std::pair; typedef set<const char*>::const_iterator set_iter; struct cmp_op { int operator() (const char* x,const char* y) const { int r = strcmp(x,y); //cout << "cmp: " << x << ((r)?((r>0)?" > ":" < "):" == ") << y << endl; return r; } }; int main() { //first char ignored, ensures unique pointers const char* a[] = {"1bb","2aa","3aa","4bb","5cc","6aa","7bb","8cc","9bb"}; const size_t n = sizeof(a)/sizeof(*a); //using custom (strcmp) comparator set<const char*,cmp_op> s; (int i=0; i<n; ++i) { cout << "insert(" << (void*)(a[i]+1) << "=" << (a[i]+1) << ")" << endl; pair<set_iter,bool> r = s.insert(a[i]+1); if (r.second) cout << "ok"; else {cout << "dup => " << (void*)(*r.first) << "=" << (*r.first);} cout << endl << endl; } cout << n << " strings, " << s.size() << " unique:" << endl; set_iter it=s.begin(); cout << (void*)(*it) << "=" << *it; while (++it!=s.end()) cout << ", " << (void*)(*it) << "=" << *it; cout << endl; return 0; }
i'm using mingw gcc 4.8.1 on windows; testing ubuntu produces same result.
your comparison function not implement strict weak ordering, because returns true
whenever lhs not equal rhs. need change logic return true when 1 "less than" other. 1 example, seems natural choice:
return r < 0;
note make intent clear, better return bool
:
bool operator() (const char* x, const char* y) const { return strcmp(x, y) < 0; }
Comments
Post a Comment