Функторы

Многие STL-алгоритмы в качестве параметров используют определенные пользователем объекты-функции и указатели на функции. И те и другие называются функторами (functors). Иногда в литературе термин «объект-функция» используется как синоним термина «функтор», однако я использую термин «объект-функция» для обозначения только экземпляров класса или структур, которые перегружают operator(). Какой из двух типов функторов лучше использовать? В большинстве случаев объект-функция более эффективен, потому что большинство компиляторов могут легко его реализовать в виде встроенной функции.

Другая причина применения объекта-функции заключается в том, что он может иметь состояние. Вы можете передавать значения его конструктору, который их сохраняет в соответствующих полях для последующего использования. По выразительным возможностям эти объекты-функции становятся сопоставимы с концепцией замыканий, которая используется в других языках программирования.

Наконец, объекты-функции могут определяться внутри другой функции или класса. Указатели на функции приходится объявлять в области видимости пространства имен.

В примере 11.4 я показал, как в функции max_element можно использовать пользовательский предикат. Этот предикат является объектом-функцией IsWeakerPlayer.

Альтернативой пользовательскому предикату, показанному в примере 11.4, является перегрузка оператора operator< для структуры ChessPlayer. Это хорошо работает в определенных случаях, но предполагает, что самой важной является сортировка игроков по рейтингу. Может оказаться, что более распространенной является сортировка по именам. Поскольку в данном случае выбор метода сортировки может быть произвольным, я предпочитаю не определять оператор operator<.

<p>11.3. Вычисление суммы и среднего значения элементов контейнера</p>Проблема

Требуется вычислить сумму и среднее значение чисел, содержащихся в контейнере.

Решение

Для расчета суммы можно использовать функцию accumulate из заголовочного файла и затем разделить ее на количество элементов, получая среднее значение. Пример 11.5 демонстрирует, как это можно сделать, используя вектор.

Пример 11.5. Вычисление суммы и среднего значения элементов контейнера

#include

#include

#include

using namespace std;

int main() {

 vector v;

 v.push_back(1);

 v.push_back(2);

 v.push_back(3);

 v.push_back(4);

 int sum = accumulate(v.begin(), v.end(), 0);

 double mean = double(sum) / v.size();

 cout << "sum = " << sum << endl;

 cout << "count = " << v.size() << endl;

 cout << "mean = " << mean << endl;

}

Программа примера 11.5 выдает следующий результат.

sum = 10

count = 4

mean = 2.5

Обсуждение

Как правило, функция accumulate обеспечивает самый эффективный и самый простой способ вычисления суммы всех элементов, содержащихся в контейнере.

Несмотря на то что данный рецепт имеет относительно простое решение, не так уж просто написать свою собственную обобщенную функцию по расчету среднего значения. В примере 11.6 показан один из способов написания такой обобщенной функции.

Пример 11.6. Обобщенная функция по расчету среднего значения

template

double computeMean(Iter_T first, Iter_T last) {

 return static_cast(accumulate(first, last, 0.0))

  / distance(first, last);

}

Перейти на страницу:

Похожие книги