A collection of utilities for comparators.
A collection of utilities for comparators.
This file contains some lightweight class templates which simplify the (re-)usage and composition of comparator classes:
- ReverseComparator (reverse the direction of comparison)
- LexicographicComparator (combine comparators lexicographically)
- PointerComparator (compare pointers like the type they point to)
We provide corresponding "make-functions" so that you will not need to write out the type names in the template instantiation.
We explain this with a simple example. First a few prerequisites.
A more convenient string class.
Definition: String.h:61
int Int
Signed integer type.
Definition: Types.h:102
unsigned int UInt
Unsigned integer type.
Definition: Types.h:94
size_t Size
Size type e.g. used as variable which can hold result of size()
Definition: Types.h:127
The class IntRealString has three data members. The class IntRealStringVector is a vector of IntRealString. We add some print() methods for convenience.
class IntRealString
{
public:
IntRealString(
Int i,
float r, String s) :
i_(i), r_(r), s_(s) {}
IntRealString(const IntRealString & rhs) :
i_(rhs.i_), r_(rhs.r_), s_(rhs.s_) {}
void print() const
{
std::cout << "(" << i_ << ", " << r_ << ", " << s_ << ")" << std::endl;
}
float r_;
String s_;
};
class IntRealStringVector :
public std::vector<IntRealString>
{
public:
void print() const
{
for (
Size i = 0; i < size(); ++i) (*
this)[i].print();
std::cout << std::endl;
}
};
Now we will exercise various ways of sorting such a vector.
Of course, we could use the std::sort algorithm with a comparison function like the following.
bool lessByInt(IntRealString left, IntRealString right)
{
return left.i_ < right.i_;
}
This is straightforward but does not generalize well. Instead we introduce three comparator classes:
struct LessByInt
{
bool operator()(IntRealString left, IntRealString right) const { return left.i_ < right.i_; }
};
struct LessByReal
{
bool operator()(IntRealString left, IntRealString right) const { return left.r_ < right.r_; }
};
struct LessByString
{
bool operator()(IntRealString left, IntRealString right) const { return left.s_ < right.s_; }
};
Typedefs from std::binary_function were removed with the removal of the std class in C++17. Types are now automatically deduced by the compiler.
Now we show various uses of the reverseComparator and lexicographicComparator function templates.
{
IntRealStringVector vec;
vec.push_back(IntRealString(1, 4.5f, "paul"));
vec.push_back(IntRealString(2, 4.5f, "josie"));
vec.push_back(IntRealString(1, 4.5f, "john"));
vec.push_back(IntRealString(2, 3.9f, "kim"));
std::cout << "After initialization:" << std::endl;
vec.print();
int main(int argc, const char **argv)
Definition: INIFileEditor.cpp:73
std::cout << "Sorted using lessByInt function:" << std::endl;
std::sort(vec.begin(), vec.end(), lessByInt);
vec.print();
std::cout << "Sorted using LessByInt comparator class:" << std::endl;
std::sort(vec.begin(), vec.end(), LessByInt());
vec.print();
std::cout << "Sorted using reversed LessByInt comparator class:" << std::endl;
vec.print();
ReverseComparator< Cmp > reverseComparator(Cmp const &cmp)
Make-function to create a ReverseComparator from another comparator without the need to specify the t...
Definition: ComparatorUtils.h:256
std::cout << "Sorted using lexicographic order: 1. LessByInt, 2. LessByReal" << std::endl;
vec.print();
LexicographicComparator< Cmp1, Cmp2 > lexicographicComparator(Cmp1 const &cmp1, Cmp2 const &cmp2)
Make-function to create a LexicographicComparator from two other comparators without the need to spec...
Definition: ComparatorUtils.h:311
std::cout << "Sorted using lexicographic order: 1. reversed LessByInt, 2. LessByReal, 3. LessByString" << std::endl;
std::sort(vec.begin(), vec.end(),
(
LessByReal()
),
LessByString()
)
);
vec.print();
And here is an application of the pointerComparator function template:
std::vector<const IntRealString *> ptr_vec;
for (
Size i = 0; i < vec.size(); ++i)
{
ptr_vec.push_back(&vec[i]);
}
std::cout << "ptr_vec before sorting" << std::endl;
for (
Size i = 0; i < ptr_vec.size(); ++i)
ptr_vec[i]->print();
std::cout << std::endl;
std::cout << "ptr_vec after sorting with pointerComparator(LessByString())" << std::endl;
for (
Size i = 0; i < ptr_vec.size(); ++i)
ptr_vec[i]->print();
std::cout << std::endl;
return 0;
}
PointerComparator< Cmp > pointerComparator(Cmp const &cmp)
Make-function to create a PointerComparator from another comparator without the need to specify the t...
Definition: ComparatorUtils.h:207
The output of the example program is:
After initialization:
(1, 4.5, paul)
(2, 4.5, josie)
(1, 4.5, john)
(2, 3.9, kim)
Sorted using lessByInt function:
(1, 4.5, paul)
(1, 4.5, john)
(2, 4.5, josie)
(2, 3.9, kim)
Sorted using LessByInt comparator class:
(1, 4.5, paul)
(1, 4.5, john)
(2, 4.5, josie)
(2, 3.9, kim)
Sorted using reversed LessByInt comparator class:
(2, 4.5, josie)
(2, 3.9, kim)
(1, 4.5, paul)
(1, 4.5, john)
Sorted using lexicographic order: 1. LessByInt, 2. LessByReal
(1, 4.5, paul)
(1, 4.5, john)
(2, 3.9, kim)
(2, 4.5, josie)
Sorted using lexicographic order: 1. reversed LessByInt, 2. LessByReal, 3. LessByString
(2, 3.9, kim)
(2, 4.5, josie)
(1, 4.5, john)
(1, 4.5, paul)
ptr_vec before sorting
(2, 3.9, kim)
(2, 4.5, josie)
(1, 4.5, john)
(1, 4.5, paul)
(1, 4.5, john)
(2, 4.5, josie)
(2, 3.9, kim)
(1, 4.5, paul)
PointerComparator< Cmp > pointerComparator(Cmp const &cmp)
Make-function to create a PointerComparator from another comparator without the need to specify the t...
Definition: ComparatorUtils.h:207
Note that pointerComparator can also be used with full-blown iterator classes. (It should work with everything that provides an operator*(), but the typedefs will always be pointers.)
Note that these templates can also be used with different types for "left" and "right".