C ++ std列表使用自定义比较器排序,该比较器依赖于对象实例的成员变量

时间:2011-12-04 02:58:35

标签: c++ list sorting std

类别:

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

我在另一个成员函数中调用非空列表中的排序:

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

我的排序功能:

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

错误:

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>]

我研究过并遇到过以下问题:

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)

如果不是因为在这个类中,sortFunc依赖于该对象实例的成员变量WORDS,那么它们就足够了。所以我不能使比较器功能(sortFunc)静态或全局

编辑:刚刚遇到这个How to sort a std:list when you need member data?并且通过建立一个朋友类提供了一个解决方案,但是可以在用户定义的类本身内完成吗?

3 个答案:

答案 0 :(得分:9)

使用lambdas:

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

使用std::bind

#include <functional>

//...
{
  using namespace std::placeholders;
  vints[i].sort(std::bind(&myClass::sortFunc, this, _1, _2));
}

答案 1 :(得分:2)

@Kerrek关于lambdas的回答更好。但是,如果必须避免使用C ++ 11功能,请使用仿函数替换sort函数。允许该仿函数存储对所需数据的引用,如下所示:

#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 :(得分:0)

===更新===

以下是不使用C ++ 11功能的解决方法:

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

为了简单起见,我省略了范围检查。 输出:

Before sort:
hello
pear
apple
After sort:
apple
hello
pear