|
Программирование >> Разработка устойчивых систем
Таблица 6.1. Шаблоны, генерирующие стандартные объекты функций Результат plus Бинарная функция minus Бинарная функция multiplies Бинарная функция divides Бинарная функция modulus Бинарная функция negate Унарная функция equal to Бинарный предикат not equal to Бинарный предикат greater Бинарный предикат less Бинарный предикат greater equal Бинарный предикат less equal Бинарный предикат loglcal and Бинарный предикат 1од1са1 ог Бинарный предикат loglcal not Унарный предикат unary negate Унарная логическая функция blnary negate Бинарная логическая функция argl + arg2 argl-arg2 argl * arg2 argl/arg2 argl%arg2 -arg argl == arg2 argl 1= arg2 argl > arg2 argl < arg2 argl >= arg2 argl <= arg2 argl 8i8iarg2 argl II arg2 largl !(унарный предикат(агд1)) !(бинарный предикат(агд1, arg2) Адаптируемые объекты функций Стандартные адаптеры (такие как bindlst() и bind2nd()) делают определенные допущения относительно обрабатываемых объектов функций. Вернемся к выражению из последней строки программы CountNotEqual.cpp: notl(binctlst(equal to<int>(). 20)) Адаптер bindlst() создает унарный объект функции типа binderlst, который просто сохраняет экземпляр equaLto<int> и значение 20. Однако функция binderlst::operator() должна знать тип своего аргумента и возвращаемого значения, иначе она не может иметь нормального объявления. Как решается эта проблема? Предполагается, что каждый объект функции предоставляет вложенные определения для этих типов. Для унарных объектов функций используются имена типов argument type и result type, а для бинарных объектов функций - имена first argument type, second argument type и result type. В этом нетрудно убедиться, просматривая реализацию bindlst() и binderlst в заголовке <functional>. Начнем с bindlst() в типичной реализации библиотеки: template <class Op. class Т> bincterlst<Op> binctlst(const Op& f. const T& val) { typedef typename Op::first argument type Argl t: return b1nderlst<0p>(f. Argl t(val)): Параметр шаблона Op, представляющий тип бинарной функции, адаптируемой адаптером bindlst(), должен содержать вложенное определение типа с именем first argument type (обратите также внимание на ключевое слово typename, которое, как отмечалось в главе 5, сообщает компилятору, что речь идет об имени вложенного типа). Теперь посмотрим, как binderlst использует имена типов Ор при объявлении своего оператора вызова функции: Внутри реализации bincterlst<Op> typename Op::result type operatorO(const typename Op: :seconct argument type& x) const: Объекты функций, классы которых предоставляют эти имена типов, называются адаптируемыми объектами функций. Поскольку указанные имена должны поддерживаться всеми стандартными объектами функций, а также любыми объектами функций, которые должны использоваться с адаптерами, в заголовочный файл <functional> входят два шаблона, автоматически определяюшие эти имена: unary function и binary function. Вы просто наследуете от этих классов при заполнении типов аргументов. Допустим, вы хотите сделать адаптируемым объект функции gt n, определение которого приводилось выше. Для этого достаточно сделать следующее: class gt n : public unary function<1nt. bool> { int value: public: gt n(int val) : value(val) {} bool OperatorO (int n) { return n > value: Как видно из определения unary function, этот шаблон просто определяет нужные типы, взятые из своих параметров шаблонов: template <class Arg. class Result> struct unary function { typedef Arg argument type: typedef Result result type: Эти типы доступны через класс gt n, поскольку класс открыто наследует от unary function. Шаблон binary function работает аналогично. Другие примеры объектов функций Следующий пример, FunctionObjects.cpp, содержит простые тесты для большинства стандартных шаблонов объектов функций. Он показывает, как использовать каждый шаблон и как он себя ведет. Для удобства в программе задействованы следующие генераторы: : С06:Generators.h Различные способы заполнения интервалов #ifndef GENERATORS H #define GENERATORSJ linclude <cstring> linclude <set> linclude <cstdlib> Генератор, пропускающий числа: class SkipGen { int i: int skp: public: SkipGenOnt start = 0. int skip = 1) : Kstart). skp(skip) {} int OperatorO О { Генератор, выдающий уникальные случайные числа в интервале от О до mod: class URandGen { std::set<int> used: int limit: public: URandGenCint lim) : limit(lim) {} int operatorO О { while(true) { int i = int(std::rand()) % limit: if(used.find(i) == used.endO) { used.insert(i): return i: Генератор случайных символов: class CharGen { static const char* source: static const int len: public: char operatorOO { return source[std::rand() % len]: : C06:Generators.cpp {0} #include Generators.h const char* CharGen::source = ABCDEFGHIJK LMNOPQRSTUVWXYZabcdefghi j к1mnopqrstuvwxyz : const int CharGen::len = strien(source): /:- Эти функции-генераторы используются во многих примерах этой главы. Объект функции SkipGen возвращает следующее число математической прогрессии, разность которой хранится в переменной skp. Объект URandGen генерирует уникальное случайное число в заданном интервале (в нем используется контейнер set, описанный в следующей главе). Объект CharGen возвращает случайный алфавитный символ. Пример программы с генератором URandGen: : C06:FunctionObjects.cpp {-bor} Демонстрация некоторых стандартных объектов функций из стандартной библиотеки С++ {L} Generators #include <algorithm> #include <cstdlib> #include <ctime> #include <functional> linclude <iostream> linclude <iterator> linclude <vector> 1nt г = 1: 1 += skp; return г;
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |