std::sort
is used to sort STL collections. If the elements in the collection you are sorting can be compared simply by calling operator<
and the collection in question is a vector
, then sorting is very simple:
std::sort(collection.begin(), collection.end());
If the collection in question is not a vector
but a list
as in your case, then you can't use the general version of std::sort
, but you can use std::list
's version instead:
list<int> numbers;
numbers.sort();
STL's sort
, along with most other algorithms in the STL, come in two flavors. One is the simple version we have already seen, which just uses operator<
to do the comparison of two elements. The other is a 'predicated' version, which instead of using operator<
uses a comparison functor you provide. This is what you need to use in your case. There is a predicated version of sort
for list
, and this is what you need to use in your case.
You can create a functor in a number of ways, but one of the most useful is to derive a class from std::unary_function
or from std::binary_function
, depending on how many arguments your functor will take -- in your case, two. Override the function-call operator, operator()
and add the code that compares two elements:
class compare_functor : public std::binary_function<Move, Move, bool>
{
public:
bool operator(const Move& lhs, const Move& rhs) const
{
int left_val = lhs.Value();
int right_val = rhs.Value();
return left_val < right_val;
};
Here is a complete working example that puts everything together. In this program, instead of having a list of Move
s, I have a list of 10 string
s. Each string
is 6 random characters. The list is populated by the call to generate_n
, which uses the functor generator
to create each random string. Then I dump that list of strings, along with their values, by calling copy
and passing an output iterator that dumps the values to stdout (ostream_iterator
). The value of each string is simply a sum of the numeric value of each character, computed by the function strng_val
.
Then I sort the list using list
's predicated version of sort
. The comparison predicate used by sort
is evaluator
. Then I finally dump the resulting list and the string values to the screen again as above:
#include <cstdlib>
#include <iostream>
#include <list>
#include <string>
#include <algorithm>
#include <ctime>
#include <sstream>
using namespace std;
class generator
{
public:
generator() { srand((unsigned)time(0)); }
string operator()() const
{
string ret;
for( int i = 0; i < 6; ++i )
ret += static_cast<char>((rand()/(RAND_MAX/26)) + 'A');
return ret;
}
};
unsigned string_val(const string& rhs)
{
unsigned val = 0;
for( string::const_iterator it = rhs.begin(); it != rhs.end(); ++it )
val += (*it)-'A'+1;
return val;
};
class evaluator : public std::binary_function<string,string,bool>
{
public:
bool operator()(const string& lhs, const string& rhs) const
{
return string_val(lhs) < string_val(rhs);
}
};
class string_dumper : public std::unary_function<string, string>
{
public:
string operator()(const string& rhs) const
{
stringstream ss;
ss << rhs << " = " << string_val(rhs);
return ss.str();
}
};
int main()
{
// fill a list with strings of 6 random characters
list<string> strings;
generate_n(back_inserter(strings), 10, generator());
// dump it to the screen
cout << "Unsorted List:\n";
transform(strings.begin(), strings.end(), ostream_iterator<string>(cout, "\n"), string_dumper());
// sort the strings according to their numeric values computed by 'evaluator'
strings.sort(evaluator()); // because this is a 'list', we are using list's 'sort'
// dump it to the screen
cout << "\n\nSorted List:\n";
transform(strings.begin(), strings.end(), ostream_iterator<string>(cout, "\n"), string_dumper());
return 0;
}