Программирование >>  Немодифицирующие последовательные алгоритмы 

1 ... 42 43 44 [ 45 ] 46 47 48 ... 78


В функции main этой программы функциональные классы {square и cube) используются в качестве параметров шаблона. Мы можем считать, что cont<T> является ограниченным вариантом контейнера, поскольку он может хранить только одно число целого типа. Однако этот класс является довольно общим в том плане, что тип-параметр Г может быть любым функциональным классом, функциональный вызов которого принимает целочисленный аргумент и возвращает целочисленное значение. В нашем примере такими классами являются square и cube. Хотя программа funobj2.cpp выглядит надуманной, она может помочь разобраться с более интересными случаями. Например, контейнер priorityjqueue также требует функциональный класс в качестве параметра, как мы видели в конце предыдущей главы.

Функции operatorQ имеют в нашем примере только один аргумент, хотя часто используются функции с двумя аргументами, как, например, в случае очередей с приоритетами. Приведем пример работы функциональных объектов с двумя аргументами функции. Определим шаблонный класс PairSelect, содержащий функцию печати, которая выводит меньший элемент пары в соответствии с определенным нами отношением меньше чем , задаваемым параметром шаблона. Также в виде параметра шаблона мы зададим тип элементов пары. Следующая программа использует два отношения упорядочения. Они реализованы в виде бинарных предикатов, то есть функций, которые имеют два аргумента и возвращают логическое значение. Наш первый бинарный предикат, LessThan, является шаблоном, поэтому он применим к любому типу, для которого определен оператор <. Второй предикат, CompareLastDigits, является обьиным, не шаблонным, функциональным классом, который практически совпадает с функциональным классом, определенным в последнем разделе предьщущей главы, только результат его вызова равен true, если последняя цифра первого аргумента меньше, чем у второго, и false - в противном случае.

funobj3.cpp: Функция operator!) как бинарный предикат.

#include <iostream.h>

template <class Т> struct LessThan {

bool operator 0 (const T &x, const T &y)const

{ return X < y;

struct CompareLastDigits {

bool operator 0 (int x, int y)const

{ return X % 10 < у % 10;



template <class Т, class Compare> class PairSelect { public:

PairSelect(const T &x, const T &y): a(x), b(y){} void PrintSmallerO const

{ cout (CompareO (a, b) ? a : b) endl; }

private: Та, b;

int mainO

{ PairSelect<double, LessThan<double> > P(123.4, 98.7); P.PrintSmallerO; Вывод: 98.7

PairSelect<int, CompareLastDigits> Q(123, 98); Q.PrintSmaller0; Вывод: 123 return 0;

Эта программа сначала выводит значение 98.7, потому что оно меньше другого элемента объекта Q - 123.4. После этого она выводит 123, поскольку последняя цифра этого числа - 3 - меньше, чем последняя цифра числа 98.

Шаблон less<T>, определенный в STL, очень похож на шаблонный класс LessThan<T> из программы/мпоуЗ.срр. В заголовке functional можно найти следующее определение:

template <class Т>

struct less: binary function<T, Т, bool> {

bool operator0 (const T& x, const T& y) const

{ return X < y;

Единственное отличие этого класса из STL от нашего класса LessThan заключается в том, что класс kss наследует от базового класса binary Junction. Этот класс не содержит никаких членов, за исключением нескольких определений типов с помощью typedef, то же относится к унарному аналогу unary Junction. Следующие определения этих классов также находятся в заголовке functional:

template <class Arg, class Result> struct unary function {

typedef Arg argument type;

typedef Result result type;

template <class Argl, class Arg2, class Result> struct binary function {

typedef Argl first argument type;



typedef Arg2 second argument type; typedef Result result type;

Для наших теперешних целей мы не используем типы, определенные в этих базовых классах, но они нужны для работы привязок и отрицателей, которые рассмотрены далее.

Как можно легко предположить, программа funobj3.cpp будет работать точно так же, если мы заменим наш собственный шаблонный класс LessThan<T> на шаблонный класс STL less<T>. Для этого можно изменить программу следующим образом;

1. В начале текста программы добавить две строки #include <functional> (или #include <algorithm>) и using namespace std.

2. Убрать определение класса LessThan.

3. Заменить LessThan на less во второй строке функции main.

6.2. Унарные предикаты и привязки

в математике мы можем превратить функцию двух аргументов в функцию одного аргумента, если один из аргументов сделаем константой. Например, мы можем определить функцию g как

g(x)=/(x, с)

где с является константой. Предположим, что мы хотим использовать шаблон STL less<T> для того, чтобы сосчитать, сколько значений, меньших 100, содержится в целочисленном массиве а из десяти элементов. В разделе 2.3 мы видели, что для решения таких задач существует алгоритм countjf, но он использует унарный предикат, а не бинарный. Это логично, ведь мы имеем дело с условием

х< 100

в котором присутствует только одна переменная. Это условие, очевидно, является частным случаем выражения

х<у

Мы говорим, что хотим привязать (bind) второй аргумент less<T> к значению 100. В STL это достигается с помощью использования привязки, которая является одним из видов адаптера функции. Чтобы превратить бинарный предикат в унарный, привязав его второй аргумент, мы используем привязку bind2nd. В нашем примере требуется использовать выражение

bind2nd(less<int>(), 100)



1 ... 42 43 44 [ 45 ] 46 47 48 ... 78

© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки.
Яндекс.Метрика