ultimatepp/tutorial/CoreTutorial/Compare.cpp
cxl 6c22e727de New Core Tutorial
git-svn-id: svn://ultimatepp.org/upp/trunk@10538 f0d560ea-af0d-0410-9eb7-867de7ffcac7
2016-12-12 10:08:40 +00:00

134 lines
2.9 KiB
C++

#include "Tutorial.h"
void ComparableTutorial()
{
/// .SgnCompare and CombineCompare
/// Traditional approach of C language of representing comparison results was 3-state:
/// comparing a and b results in negative value (if a < b), zero (if a == b) or positive
/// value (a > b). In C++ standard library, comparisons are usually represented with `bool`
/// predicates.
/// However, with `bool` predicate it becomes somewhat more difficult to provide
/// comparisons for composite types:
struct Foo {
String a;
int b;
int c;
// we want to order Foo instances by a first, then b, then c
bool operator<(const Foo& x) const {
return a < x.a ? true
: a == x.a ? b < x.b ? true
: b == x.b ? false
: c < x.c
: false;
}
};
/// U++ provides standard function `SgnCompare`, which returns negative value/zero/positive
/// in "C style":
int a = 1;
int b = 2;
DUMP(SgnCompare(a, b));
DUMP(SgnCompare(b, a));
DUMP(SgnCompare(a, a));
/// Default implementation of `SgnCompare` calls `Compare` method of value:
struct MyClass {
int val;
int Compare(const MyClass& x) const { return SgnCompare(val, x.val); }
};
/// `SgnCompare` is now defined for `MyClass`:
MyClass u, v;
u.val = 1;
v.val = 2;
DUMP(SgnCompare(u, v));
DUMP(SgnCompare(v, u));
DUMP(SgnCompare(v, v));
/// Now getting back to `Foo`, with `SgnCompare` `operator<` becomes much less difficult:
struct Foo2 {
String a;
int b;
int c;
bool operator<(const Foo2& x) const {
int q = SgnCompare(a, x.a);
if(q) return q < 0;
q = SgnCompare(b, x.b);
if(q) return q < 0;
q = SgnCompare(c, x.c);
return q < 0;
}
};
/// Alternatively, it is possible to define just `Compare` method and use `Comparable`
/// ^https://en.wikipedia.org/wiki/Curiously_recurring_template_pattern:CRTP idiom^ to
/// define all relation operators:
struct Foo3 : Comparable<Foo3> {
String a;
int b;
int c;
int Compare(const Foo3& x) const {
int q = SgnCompare(a, x.a);
if(q) return q;
q = SgnCompare(b, x.b);
if(q) return q;
return SgnCompare(c, x.c);
}
};
Foo3 m, n;
m.a = "A";
m.b = 1;
m.c = 2;
n.a = "A";
n.b = 1;
n.c = 3;
DUMP(m < n);
DUMP(m == n);
DUMP(m != n);
DUMP(SgnCompare(m, n));
/// While the content of `Compare` method is trivial, it can be further simplified using
/// `CombineCompare` helper class:
struct Foo4 : Comparable<Foo4> {
String a;
int b;
int c;
int Compare(const Foo4& x) const {
return CombineCompare(a, x.a)(b, x.b)(c, x.c);
}
};
Foo4 o, p;
o.a = "A";
o.b = 1;
o.c = 2;
p.a = "A";
p.b = 1;
p.c = 3;
DUMP(o < p);
DUMP(o == p);
DUMP(o != p);
DUMP(SgnCompare(o, p));
///
}