4

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?

4
  • Please don't use all uppercase identifiers (except for macros, where you should use them). Commented Dec 4, 2011 at 3:09
  • Fixed. Was trying to make the relevant info stand out. Commented Dec 4, 2011 at 3:12
  • Is this C++11? Can you use lambdas or bind()? Commented Dec 4, 2011 at 3:15
  • 1
    ¤ The basic idea is to pass an object that has an operator() so that it can be used as function. That's called a functor. In C++11 you can create such a beast on the fly, as a "lambda". In C++98/03 you have to either define a class for it, or use some third party library such as Boost. E.g. you can use boost::bind to have a pointer to your words, passed to your real function. Cheers & hth., Commented Dec 4, 2011 at 3:16

2 Answers 2

9

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));
}
Sign up to request clarification or add additional context in comments.

3 Comments

@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?
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
@Kerrek SB: Thanks, forgot the specify the std. @ Rob: I'm not sure what you are referring to.
2

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

1 Comment

Can't beat the classiness of lambdas, but that requires a C++11 which I currently cannot use.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.