使用自定义谓词对类成员进行排序

时间:2012-06-27 05:03:37

标签: c++

我有一个看起来像这样的场景:

#include <algorithm>
using namespace std;

// a "heavy" struct with lots of members
struct B {
  int key;
  // other members  
} 

class A {
  vector<B> bs;
}

我想按键排序bs。现在,我过去做过这种方式以避免交换B(因为它们相当沉重),就是定义一个索引向量并对索引进行排序。如果bs不是类成员,则此方法有效。

e.g。

vector<B> bs;
vector<size_t> indices;

bool pred(size_t i, size_t j) { return bs[i] < bs[j]; }

indices.resize(bs.size());
for (size_t i = 0; i < bs.size(); i++) indices[i] = i;
std::sort(indices.begin(), indices.end(), pred);

但是,当bs是类成员时,这种“技术”会失败,因为谓词只能带两个参数。特别是,没有办法传递“这个”。

我可以看到三种不同的方法来解决这个问题:

  • 不要打扰指数。只需重载运算符<来处理B的实例。整个索引只是过早的优化: - )
  • 拥有指向bs的全局指针,在调用sort之前设置它,并在pred中使用它。
  • 使用闭包。除非我不使用C ++ 11,否则这将非常酷。

还有其他办法吗?谢谢!

2 个答案:

答案 0 :(得分:1)

如果您可以为B编写轻量级交换,那么问题就不存在了:sort将使用您的轻量级交换。

如果这不是一个选项,你可以在向量中存储(智能)指针,并对指针进行排序。

或者让你的班级使用pimpl习语然后交换,因为几乎是免费的。

绝对不要使用全局指针,因为有时某人会想要使这个代码线程安全,并且用于排序的全局容器在任何尝试对这些对象进行多线程排序时都会是一个巨大的刺。

答案 1 :(得分:1)

假设b位于class A并且可通过名为get的成员函数访问,您可以编写这样的仿函数:

struct Comparator
{
  Compartor(A& a): m_a(a){}
  bool operator()(int i, int j) const
  {
    return m_a.get(i) < m_a.get(j);
  }

 A& m_a;
};

并像这样使用它:

A a;
std::sort(indices.begin(), indices.end(), Comparator(a));