C ++ set with arbitrary comparator

I have the following C ++ code

#include <set>
#include <string>
#include <iostream>
using namespace std;

class Pair {
  public:
    string lhs;
    string rhs;
    Pair();
    Pair( string l, string r ) {
      lhs=l;
      rhs=r;
    };
};

struct compare {
  bool operator()(const Pair& a, const Pair& b) const{
    if ( ( a.lhs == b.lhs && a.rhs == b.rhs ) || ( a.lhs == b.rhs && a.rhs == b.lhs ) ) {
      cout << "MATCH" << endl;
    }
    return ( a.lhs == b.lhs && a.rhs == b.rhs ) || ( a.lhs == b.rhs && a.rhs == b.lhs );
  }
};

int main () {
  set<Pair, compare > s;
  Pair p( string("Hello"), string("World") );
  s.insert(p);
  cout << s.size() << "\n";
  Pair q( string("World"), string("Hello") );
  s.insert(q);
  cout << s.size() << "\n";
  compare cmp;
  cout << cmp( p, q );

  return 0;
}

Calling the compiled code gives:

1
MATCH
MATCH
2
MATCH

Once set s ends and Couples p and q, despite the fact that the comparator identifies them as identical. Why?

Any help would be greatly appreciated!

UPDATE:

Thank you very much for the excellent answers and your kind and professional help. As you may have guessed, I'm pretty new to C ++.

Anyway, I was wondering if Antoine can respond with a lambda expression?

Sort of:

std::set< …, [](){ my_comparator_code_here } > s;

????

+4
source share
4 answers

, compare , , std::less. , , < .

. , :

bool operator()(const Pair & a, const Pair & b) {
  const bool swapA = a.lhs < a.rhs;
  const std::string & al = swapA ? a.lhs : a.rhs;
  const std::string & ar = swapA ? a.rhs : a.lhs;
  const bool swapB = b.lhs < b.rhs;
  const std::string & bl = swapB ? b.lhs : b.rhs;
  const std::string & br = swapB ? b.rhs : b.lhs;
  return al < bl || (al == bl && ar < br);
}

, , .

: : al < bl || (al == bl && ar < br), .

, ( N) ( 2). std::set . " 2" Pair .

, Pair, min() max(). , operator<, compare:

struct Pair {
  string lhs, rhs;
  Pair();
  Pair( string l, string r ) : lhs(l), rhs(r) {}
  const std::string & min() const { return lhs < rhs ? lhs : rhs; }
  const std::string & max() const { return lhs < rhs ? rhs : lhs; }
  bool operator<(const Pair& b) const {
    return min() < b.min() || (min() == b.min() && max() < b.max());
  }
};
+2

a std::set ( ) , . operator< .

( ), undefined. ++.

, , , operator< .

, std::pair<std::string, std::string> , ?

, , , , set , first second, . @Antoine , .

+6

set, map , lower_bound sort, , ( , a <).

3 :

  • : not (a < a)
  • : a < b not (b < a)
  • transitive: a < b b < c a < c

<.

, , ( not (a < b) and not (b < a) ). set map , multiset multimap .

, , , ==, . - <.

, - , < ( == ), . , std::tuple<std::string, std::string> , ; , std::tuple<std::string const&, std::string const&> , std::tie.

, :

struct comparator {
    bool operator()(Pair const& left, Pair const& right) const {
        return std::tie( left.a,  left.b)
             < std::tie(right.a, right.b);
    }
};

. , , . , , , , (, )


EDIT: , .

, , , a b . , ; , :

struct comparator {
    bool operator()(Pair const& left, Pair const& right) const {
        auto uleft = left.a < left.b ? std::tie(left.a, left.b)
                                     : std::tie(left.b, left.a);
        auto uright = right.a < right.b ? std::tie(right.a, right.b)
                                        : std::tie(right.b, right.a);

        assert(get<0>(uleft) <= get<1>(uleft) and "Incorrect uleft");
        assert(get<0>(uright) <= get<1>(uright) and "Incorrect uright");

        return uleft < uright;
    }
}; // struct comparator
+3

set , , , ( : , : comp (a, b) &! comp (, )). .

, , . . AS, . . , , , , false .

if (( a.lhs == b.lhs && a.rhs == b.rhs ) || ( a.lhs == b.rhs && a.rhs == b.lhs )) return false;
//ordinary lexicographical compare
if( a.lhs < b.lhs) return true;
else if( a.lhs == b.lhs && a.rhs < b.rhs) return true;
else return false;

"!", . , , . , , , .

DISCLAIMER IS ALWAYS WRONG TECHNICAL PROTECTION, ANTOIN - THE RIGHT ONE

+1
source

All Articles