new TSetOf<TStandardText>(NIL, NIL); // no comparators
TStandardText *d = collection->Find(b);
// create comparator here TSetOf<TStandardText>* collection = new TSetOf<TStandardText>(comparator, NIL); // use it here
TComparator<TStandardText>* comparator = new TMCollectibleComparator<TStandardText>(); // define comparator
This same statement is used in the following program which properly weeds out duplicate TStandardText elements from a set where duplicates are defined by the isEqual member function of the TStandardText class.
int main() { TComparator<TStandardText>* comparator = new TMCollectibleComparator<TStandardText>(); TSetOf<TStandardText>* collection = new TSetOf<TStandardText>(comparator, NIL); collection->Add(new TStandardText("one")); collection->Add(new TStandardText("two")); collection->Add(new TStandardText("three")); collection->Add(new TStandardText("one")); collection->Add(new TStandardText("two")); collection->Add(new TStandardText("three")); printCollection(collection); delete collection; return 0; }
0> one 1> two 2> three
NOTE Comparators encapsulate a mechanism, like an API. For example many C++ objects use operator== and operator != for comparison. In addition, MCollectible objects use ::IsEqual. The CommonPoint system provides comparators to cover these cases. Only in a case where a programming organization establishes a domain-wide standard for object comparison based on IsSame is it necessary to create a new subclass of TComparator to use with CommonPoint collections. As mentioned this situation rarely occurs. It's usually easier to take advantage of existing CommonPoint comparators which user operator==, !=, <, and >.
Think of comparators as plug-in components used by collection objects. You select among different comparators to get the exact behavior you want, then plug the comparator into the collection. You don't have to define the behavior of the comparator as it determines how to perform comparisons based on a virtual function descended from TComparator::Compare.
For simple comparisons of TStandardText objects, the comparator calls TStandardText::IsEqual. The result of a call to this virtual function is an enumerated constant whose type is EComparisonResult. Generally you don't need to worry about how Compare and IsEqual work exactly, except to know that a collection uses the Compare function of a comparator which in turn invokes IsEqual (which may call IsSame) when it needs to test collection elements for equality.
Sorted sequences require a little more protocol than is provided by the TMCollectibleComparator class of comparators used by sets. Sorted sequences not only need to compare elements for equality and identity, but also must compare elements to determine if they are less than, greater than, or equal to other elements.
The class that does this is TMOrderableCollectibleComparator. In addition to the ::Compare virtual member function inherited from TComparator, TMOrderableCollectibleComparator provides a virtual member function called ::OrderedCompare. Sorted sequences invoke OrderedCompare when determining the internal order of collection elements. The elements placed in such a collection must respond to ::IsGreaterThan and ::IsLessThan messages which are sent by the comparator. In order to change the class of the collection in the previous example from a set to a sorted sequence, you would have to declare the comparator for the collection as follows.
TMOrderableCollectibleComparator<TStandardText>* comparator = new TMOrderableCollectibleComparator<TStandardText>();
TSortedSequenceOf<TStandardText>* collection = new TSortedSequenceOf<TStandardText>(comparator, NIL);
int main() { TMOrderableCollectibleComparator<TStandardText>* comparator = new TMOrderableCollectibleComparator<TStandardText>(); TSortedSequenceOf<TStandardText>* collection = new TSortedSequenceOf<TStandardText>(comparator, NIL); collection->Add(new TStandardText("one")); collection->Add(new TStandardText("two")); collection->Add(new TStandardText("three"));
0> one 1> one 2> three 3> three 4> two 5> two