#include #include #include #include #include // for bind() #include // for ostream_iterator using namespace std; using std::placeholders::_1; using std::placeholders::_2; //------------------------------------------------------------- // A two-argument comparison function for vector arguments. // The argument vectors must be of the same length. Comparison // is done element by element, starting from element 0. //------------------------------------------------------------- template bool cmp2Template( const vector &lhs, const vector &rhs ) { for ( unsigned int idx=0; idx bool cmp3Template( const vector &lhs, const vector &rhs, const vector &index) { for ( auto idx : index ) { if ( lhs[idx] < rhs[idx] ) return true; if ( rhs[idx] < lhs[idx] ) return false; } return false; } //-------------------------------------------------------------- // Prints the vector of vectors. The string used to separate // vector elements is an argument, but has a default value that // will be used if the caller doesn't provide that argument. // (The default parameter(s) must come last in the list.) //-------------------------------------------------------------- template void printThem( const string &title, vector> &vecvec, const char* sep = ", ") { cout << endl << title << endl; for ( auto & el : vecvec ) { cout << "\t"; auto end = --el.end(); for_each( el.begin(), end, [sep](T val){ cout << val << sep; } ); cout << *end << endl; } } //-------------------------------------------------------------- // Function object definition. It exports a two argument function, // with signature that required by sort()'s comparison argument. // In that exported function it calls our three argument comparison function. //-------------------------------------------------------------- template class FuncObj { private: vector idx; // the sort order vector public: FuncObj(const vector &idxArg) : idx(idxArg) { } bool operator() ( const vector &lhs, const vector &rhs) { return cmp3Template(lhs, rhs, idx); } }; //------------------------------------------------------------- // main line //------------------------------------------------------------- int main() { //------------------------------------------------------------ // We group these declarations together here because they have // to agree on a type for the data. //------------------------------------------------------------ // The logical '0' of the data type. // Change the type of the initialization value of this variable // to change the type of everything... auto valueBase = 1; // auto valueBase = 'a'; typedef decltype(valueBase) ValueType; auto cmp2 = cmp2Template; auto cmp3 = cmp3Template; // the basic values from which the test data is created vector rawdata = { ValueType(valueBase + 2), ValueType(valueBase + 1), ValueType(valueBase + 0) }; //----------------------------------------------------- // Initialize and print the data we'll be sorting //----------------------------------------------------- vector> data; for ( auto el0 : rawdata ) for ( auto el1 : rawdata ) for ( auto el2 : rawdata ) data.push_back( vector{el0, el1, el2} ); printThem("Original data (reverse order)", data, " "); //----------------------------------------------------- // Sort in natural order. Use indirect call to two argument // comparison function //----------------------------------------------------- string title = "Sort in natural order. Use direct reference to two argument comparison function"; sort( data.begin(), data.end(), cmp2 ); printThem(title, data, ", "); //----------------------------------------------------- // Sort on {1, 2, 0}. Use function object. //----------------------------------------------------- title = "Sort on {1, 2, 0}. Use function object to invoke 3 argument comparison function."; FuncObj funcObj(vector{1,2,0}); sort( data.begin(), data.end(), funcObj ); printThem(title, data); //----------------------------------------------------- // Sort on {2, 0, 1}. Use a lambda expression as sort function //----------------------------------------------------- title = "Sort on {2, 0, 1}. Use a lambda expression to invoke 3 argument sort function"; sort( data.begin(), data.end(), [&cmp3](const vector &lhs, const vector &rhs) -> bool { return cmp3(lhs, rhs, vector{2,0,1}); } ); printThem(title, data); //----------------------------------------------------- // Sort on {0, 2, 1}. Use bind //----------------------------------------------------- title = "Sort on {0, 2, 1}. Use bind adapter to invoke 3 argument comparison function."; sort( data.begin(), data.end(), bind(cmp3, _1, _2, vector{0,2,1}) ); printThem(title, data); return 0; }