Sorting a std C ++ file using a custom comparator that depends on a member variable for an object instance

Grade:

Class: private: ... vector<string> words; vector< list<int> > vints; public: myFunction(...) 

I call sorting on a non-empty list in another member function:

 void myClass::myFunction (...) { ... if (!vints[i].empty()) vints[i].sort(sortFunc); ... } 

My sort function:

 bool myClass::sortFunc(const int& i, const int& j) { return (words[i] < words[j]); } 

Error:

 error: no matching function for call to 'std::list<int, std::allocator<int> >::sort(<unresolved overloaded function type>)' /usr/include/c++/4.4/bits/list.tcc:301: note: candidates are: void std::list<_Tp, _Alloc>::sort() [with _Tp = int, _Alloc = std::allocator<int>] /usr/include/c++/4.4/bits/list.tcc:378: note: void std::list<_Tp, _ Alloc>::sort(_StrictWeakOrdering) [with _StrictWeakOrdering = bool (SuperWordSearch::*) (const int&, const int&), _Tp = int, _Alloc = std::allocator<int>] 

I researched and came across the following questions:

C ++ Custom comparison function for list :: sort

The problem of sorting a list of pointers

Error in std :: list :: sort with custom comparator (expected primary expression before ')' token

and they would be enough if it weren’t for the fact that in this class sortFunc depends on the WORDS member variable for this instance of the object. Therefore, I cannot make the comparison function (sortFunc) static or global

EDIT: just came across this How to sort a std list: when do you need member data? and he offers a solution by creating a friends class, but can this be done inside the user class itself?

+4
source share
3 answers

@ Kerrek's answer involving lambda is better. But if you should avoid C ++ 11 functions, replace the sort function with a functor. Let this functor store a reference to any data like this:

 #include <vector> #include <list> #include <string> class myClass { private: std::vector<std::string> words; std::vector<std::list<int> > vints; // Instead of sortFunc, use sortFunctor. A functor can be used in place // of a function in many places, and it can carry state (like a reference // to the data it needs). struct sortFunctor { const std::vector<std::string>& words; sortFunctor(const std::vector<std::string>& words) : words(words) { } bool operator()(int i, int j) { return words[i] < words[j]; } }; public: void myFunction() { vints[0].sort(sortFunctor(words)); } myClass() { words.push_back("apple"); words.push_back("berry"); std::list<int> l; l.push_back(0); l.push_back(1); vints.push_back(l); } }; int main () { myClass object; object.myFunction(); } 
+2
source

With lambdas:

 vints[i].sort([&words](int i, int j) { return words[i] < words[j]; }); 

With std::bind :

 #include <functional> //... { using namespace std::placeholders; vints[i].sort(std::bind(&myClass::sortFunc, this, _1, _2)); } 
+9
source

=== UPDATED ===

The following is a workaround without using C ++ 11 features:

 #include <exception> #include <iostream> #include <list> #include <string> #include <vector> using namespace std; class MyClass { private: vector<string*> words; vector< list<string*> > vptrs; static bool sortFunc(const string* s1, const string* s2) { return (*s1 < *s2); } public: MyClass() { vptrs.push_back(list<string*>()); } ~MyClass() { for (int i = 0; i < vptrs.size(); ++i) vptrs[i].clear(); for (int i = 0; i < words.size(); ++i) delete words[i]; } void addWord(const char* s) { words.push_back(new string(s)); } void setWord(int i, const char* s) { *words[i] = s; } void addIndex(int i, int j) { vptrs[i].push_back(words.at(j)); } void sort(int i) { if (!vptrs[i].empty()) vptrs[i].sort(sortFunc); } void print(int i) { list<string*>::iterator s; for (s = vptrs[i].begin(); s != vptrs[i].end(); ++s) cout << **s << endl; } }; int main(int argc, char **argv) { try { MyClass* c = new MyClass(); c->addWord("apple"); c->addWord("hello"); c->addWord("world"); c->addIndex(0, 1); c->addIndex(0, 2); c->addIndex(0, 0); c->setWord(2, "pear"); cout << "Before sort:" << endl; c->print(0); c->sort(0); cout << "After sort:" << endl; c->print(0); delete c; } catch (exception e) { cout << e.what() << endl; } getchar(); return 0; } 

I skipped range checking for simplicity. Output:

 Before sort: hello pear apple After sort: apple hello pear 
0
source

Source: https://habr.com/ru/post/1384533/


All Articles