Re: Generic compare function
On Jan 18, 8:43 am, Seungbeom Kim <musip...@bawi.org> wrote:
[snipped]
I used std::pair just as an easy example, but the same phenomenon can
happen in any structure where the lexicographical ordering ("compare
field A first, and field B second, ...") is needed.
Yep, such as gene sequence sorting, etc.
bool operator<(const pair<A, B, C>& x, const pair<A, B, C>& y)
{
return x.first < y.first
|| (!(y.first < x.first)
&& (x.second < y.second
|| (!(y.second < x.second)
&& x.third < y.third)));
}
// I'm not even sure if I got that right...
// This would be easier to write and understand:
bool operator<(const pair<A, B, C>& x, const pair<A, B, C>& y)
{
if (x.first < y.first) return true;
if (y.first < x.first) return false;
if (x.second < y.second) return true;
if (y.second < x.second) return false;
return x.third < y.third;
}
// This is intuitive and efficient!
int compare(const pair<A, B, C>& x, const pair<A, B, C>& y)
{
if (int r = compare(x.first, y.first)) return r;
if (int r = compare(x.second, y.second)) return r;
return compare(x.third, y.third);
}
And the inefficiency could get higher with a deeper level of nesting.
The form of the code above is pratically identical to that of the
actual code below for comparing bytes of Ethernet address:
---- START CODE ----
friend int signum (const Bytes &a, const Bytes &b)
{
if (int s = ::signum(a.buffer[5], b.buffer[5])) return s;
if (int s = ::signum(a.buffer[4], b.buffer[4])) return s;
if (int s = ::signum(a.buffer[3], b.buffer[3])) return s;
if (int s = ::signum(a.buffer[2], b.buffer[2])) return s;
if (int s = ::signum(a.buffer[1], b.buffer[1])) return s;
return ::signum(a.buffer[0], b.buffer[0]);
}
bool operator == (const Bytes &that) const {return signum (*this,
that) == 0;}
bool operator != (const Bytes &that) const {return signum (*this,
that) != 0;}
bool operator > (const Bytes &that) const {return signum (*this,
that) > 0;}
bool operator < (const Bytes &that) const {return signum (*this,
that) < 0;}
bool operator >= (const Bytes &that) const {return signum (*this,
that) >= 0;}
bool operator <= (const Bytes &that) const {return signum (*this,
that) <= 0;}
---- END CODE ----
As you might imagine, this method becomes so comfortable/regular that
after two or three iterations, it requires no forethought.
Whenever I have create a new class whose values can be ordered,
whether I intend to order them or not, immediately, I:
1. Go to one of my existing order-able classes.
2. Cut and paste the code like that above.
3. Rename old class name to new class name within the code.
4. Define signum for the new class.
5. Tuck it away for later, just in case.
Of course, existing STL code cannot benefit from "compare/signum", so
one would have to define their own containers to take advantage of
this method.
-Le Chaud Lapin-
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]