C++ std list sort with custom comparator that depends on an member variable for the object instance

13,465

Solution 1

@Kerrek's answer involving lambdas is better. But, if you must avoid C++11 features, then replace your sort function with a functor. Allow that functor to store a reference to whatever data is required, as so:

#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();
}

Solution 2

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));
}
Share:
13,465
encore2097
Author by

encore2097

Updated on June 04, 2022

Comments

  • encore2097
    encore2097 almost 2 years

    Class:

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

    I am calling a sort on non-empty list in another member function:

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

    My sorting function:

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

    The 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 have researched and come across the following questions:

    C++ Custom compare function for list::sort

    Problem sorting a list of pointers

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

    and they would have been sufficient had it not been for the fact that in this class, the sortFunc depends on the member variable WORDS for that instance of the object. So I cannot make the comparator function (sortFunc) static or global

    EDIT: Just came across this How to sort a std:list when you need member data? and it provides a solution by making a friend class, but is it possible to accomplish this inside the user-defined class itself?

  • Kerrek SB
    Kerrek SB over 12 years
    @kol: You have to spell out the predicate yourself. Every lambda can trivially be expanded into a functor; it's just noisy. Do you need help with that?
  • encore2097
    encore2097 over 12 years
    Hrm... I'm getting the following errors trying the bind method (Ubuntu linux x64, g++ v.4.4.3:) error: ‘placeholders’ is not a namespace-name error: expected namespace-name before ‘;’ token error: ‘bind’ is not a member of ‘std’ error: ‘_1’ was not declared in this scope error: ‘_2’ was not declared in this scope
  • encore2097
    encore2097 over 12 years
    @Kerrek SB: Thanks, forgot the specify the std. @ Rob: I'm not sure what you are referring to.
  • encore2097
    encore2097 over 12 years
    Can't beat the classiness of lambdas, but that requires a C++11 which I currently cannot use.