|
Программирование >> Немодифицирующие последовательные алгоритмы
В функции 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)
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |