Определение <для алгоритма сортировки STL - перегрузка оператора, функтор или автономная функция? - PullRequest
10 голосов
/ 13 марта 2010

У меня есть stl :: list, содержащий объекты класса Widget. Их нужно отсортировать по двум элементам в классе Widget.

Чтобы сортировка работала, должен быть определен компаратор меньше чем, сравнивающий два объекта Widget. Кажется, существует множество способов сделать это. Из того, что я могу собрать, можно либо:

а. Определите перегрузку оператора сравнения в классе:

bool Widget::operator< (const Widget &rhs) const

б. Определите автономную функцию, используя два виджета:

bool operator<(const Widget& lhs, const Widget& rhs);

А затем сделайте класс Widget своим другом:

class Widget {
    // Various class definitions ...
    friend bool operator<(const Widget& lhs, const Widget& rhs);
};

с. Определите функтор и затем включите его в качестве параметра при вызове функции сортировки:

class Widget_Less :
public binary_function<Widget, Widget, bool> { 
    bool operator()(const Widget &lhs, const Widget& rhs) const;
};

Кто-нибудь знает, какой метод лучше? В частности, мне интересно знать, стоит ли мне делать 1 или 2. Я искал книгу Скотта Мейера «Эффективный STL», но, к сожалению, по этому поводу ничего не сказано.

Спасибо за ваш ответ.

Ответы [ 4 ]

11 голосов
/ 13 марта 2010

Если вы сравниваете только два виджета друг с другом, используйте элемент operator <. Если вы сравниваете Widget с чем-то другим, определите глобальный operator < (версия с двумя параметрами, необязательно друг класса Widget, но это отдельная проблема.

Функтор, который вам действительно нужен, только если вы делаете что-то немного менее ортодоксальное. Выберите функтор, если сравнение «меньше» не имеет смысла в контексте виджетов. В этом случае наличие operator < может сбить с толку. Конечно, функторы все еще должны предоставлять порядок, но только потому, что это порядок, не означает, что это операция «меньше». (Например, сортировка состояний по совокупности, вероятно, лучше для функтора, чем operator <.

2 голосов
/ 13 марта 2010

а. б. Оператор сравнения для двух виджетов не является для меня интуитивно понятным. Теперь я не вижу, что он может сделать. Также, если эта функция не является интуитивно понятной, когда вам понадобится один новый оператор сравнения, что вы можете сделать в этом случае?

Я предпочитаю функтор.

1 голос
/ 13 марта 2010

Для большинства целей а. и б. подобные. Таким образом, реальный вопрос в том, когда использовать a / b, а когда использовать c.

Ответ: используйте a или b, если «меньше чем» имеет смысл для вашего объекта в однозначных терминах. Если ваш класс - число, используйте <.

Если «меньше чем» не имеет смысла в контексте вашего класса, то, пожалуйста, не перегружайте «оператор <» для вашего класса. Это запутает пользователей. Используйте c. вместо этого, либо сделайте его вложенным классом, либо введите его в свой класс, чтобы вы могли написать его как <code>Widget::Compare.

1 голос
/ 13 марта 2010

Они все должны быть одинаковыми с точки зрения производительности, но между ними есть и другие различия:

  • Первые два избавляют вас от необходимости явно указывать компаратор и могут легко использоваться с другими операциями, возможно, плохо определенными, которые не допускают явного указания компаратора.

  • Только функтор допускает дополнительные данные для сравнения. Например, если вы сравниваете int s, вы можете создать сравнение, которое сравнивает их расстояние от третьей точки P, которая будет членом экземпляра функтора.

  • Функторы, как правило, труднее читать (тем, кто не знаком с C ++).

Обратите внимание, вам не нужно наследовать binary_operator, чтобы он работал, хотя он дает вам несколько хороших typedef с.

...