2012-06-27 2 views
0

У меня есть сценарий, который выглядит следующим образом:Сортировка члена класса с помощью пользовательского предиката

#include <algorithm> 
using namespace std; 

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

class A { 
    vector<B> bs; 
} 

Я хочу, чтобы отсортировать закладной по их ключам. Теперь, как я это делал в прошлом, чтобы избежать замены Bs (поскольку они довольно тяжелые), это определить вектор индексов и отсортировать индексы вместо этого. Это работает, если bs не является членом класса.

например.

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); 

Однако, когда шс является членом класса, это «метод» не удается, потому что предикат может принимать только два параметра. В частности, нет способа передать «это».

Я вижу три пути решения этой проблемы:

  • Не связывайтесь с индексами. Просто перегружать оператор < для обработки экземпляров B. Это целая индексы вещь просто преждевременная оптимизация :-)
  • Есть глобальный указатель на bs, установите его перед вызовом sort, и использовать его в pred.
  • Использовать затворы. Это было бы неплохо, если не использовать C++ 11.

Есть ли другой способ сделать это? Благодаря!

ответ

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)); 
+0

Ницца. Не думал об использовании функтора. Благодаря! – abeln

+0

Даже лучше, я могу передать 'const B &' в конструктор 'Comparator'. Таким образом, мне не нужно предоставлять метод getter для 'bs'. – abeln

1

Если вы можете написать легкий обмен для B, тогда проблема не существует: sort будет использовать ваш легкий обмен.

Если это не вариант, вы можете хранить (умные) указатели на свой класс в векторе и сортировать указатели.

Или сделайте свой класс идиомой pimpl, а затем замените, потому что он почти свободен.

Определенно не используйте глобальный указатель, потому что когда-то кто-то захочет сделать этот код потокобезопасным, а глобальный контейнер, используемый для сортировки, будет гигантским шипом в любой попытке многопоточной сортировки этих объектов.

+0

Реализация облегченный своп - интересная идея, хотя она здесь не применима. Я помню, как в школе учился чеширский кот, но не помнил его :) – abeln

Смежные вопросы