Анимация
JavaScript


Главная  Библионтека 

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 [ 98 ] 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239

Первый аргумент и возвращаемое значение относятся к одному типу Т1, а показатель степени может относиться к другому типу 12, Передавая эту информацию binary function, мы обеспечиваем определение необходимых типов. Тем не менее вместо использования binary function типы можно определить напрямую. Как обычно бывает в STL, функциональные адаптеры соответствуют концепции чистой абстракции: любой объект, который ведет себя как объект функции, совместимый с функциональными адаптерами, является таковым. ;

Следующая программа показывает, как работать с пользовательским объектом функции fopow. В частности, продемонстрировано использование fbpow с адаптерами bindlst и bind2nd:

fo/fopowl.cpp #lnclude <iostream> #inclLide <vector> #lnclude <algorlthm> using namespace std:

Включение пользовательского обьекта функции fopow<> #lnc1ude "fopow.hpp"

int mainO (

vector<int> col 1:

Вставка элементов со значениями от 1 до 9 for Cint i=l: i<=9: ++i) { coll.push backCi):

Вывод числа 3. возведенного в степень каждого элемента transform (coll.beginO. coll.endO. . Источник

ostream iterator<int>(cout." "). Приемник

bindlst(fopow<float.int>0.3)): Операция cout « endl:

Вывод всех элементов, возведенных в степень 3 transform (coll.beginO, coll.endO. Источник

ostream iterator<int>(cout." "). Приемник

bind2nd(fopow<float.int>().3)): Операция cout « endl:

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

3 9 27 81 243 729 2187 6561 19683 1 8 27 64 125 216 343 512 729

Обратите внимание: объект функции fopow реализован для типов float и int Если использовать int как для основания, так и для показателя степени, вы сможете вызвать pow() с двумя аргументами типа int, но при этом будет нарушена



переносимость кода, поскольку в соответствии со стандартом функция pow() перегружается более чем для одного, но не для всех базовых типов:

transform (соП . begin(). coll.endO.

ostream iterdtor<int>(cout." ").

b1ndlstCfopow<1nt,int>0.3)): ОШИБКА: неоднозначность Более подробное описание этой проблемы приводится на с. 557.

Дополнительные композиционные адаптеры

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

Теоретически в библиотеке пригодились бы следующие композиционные адаптеры.

О f(g(e/m)). Общая форма унарной композиции - вложенные вызовы унарных предикатов, при которых результаты вызова предиката д() являются входными данными для предиката f(). Все выражение работает как унарный предикат.

О f{g{elem1 ,elem2)). Два элемента elemi и elem2 передаются в аргументах бинарного предиката д(), а результать!, как и в предыдущем случае, являются входными данными для унарного предиката f(). Все выражение работает как бинарный предикат.

О f{g{elem),h{elem)). Элемент elem передается двум разным унарным предикатам д() и h(), а результаты обрабатываются бинарным предикатом f(). Все выражение работает как унарный предикат.

О f{g{elem1),h{elem2)). В этой форме два элемента elemi и elem2 передаются двум разным унарным предикатам д() и h(), а результаты обрабатываются бинарным предикатом f(). Все выражение работает как бинарный предикат.

К сожалению, эти композиционные адаптеры не были стандартизированы, поэтому для них не существуют стандартных имен. В реализации STL от SGI были определены имена для двух из перечисленных адаптеров, однако сообщество программистов еще не выбрало наиболее подходящие. В табл. 8.5 приведены имена, которые мы будем использовать в этой книге.

В архиве библиотек С++ Boost (http: wvvw.boost.org) можно найти как имена, которые должны использоваться в будущем, так и их полную реализацию. Ниже описаны три адаптера, которые часто встречаются в книге.



Таблица 8.5. Возможные имена композиционных адаптеров

Функциональность

В книге

В реализации STL от SGI

f(g(elem))

compose f gx

com pose 1

f(g(eleml,elem2))

compose f gxy

f(g(elem),h(elem))

compose f gx hx

compose2

f(g(eleml),h(e[em2))

compose f gx hy

Унарные композиционные адаптеры

Унарные композиционные адаптеры являются весьма важными. Они также входят в реализацию STL от SGI.

Вложенные вычисления с использованием адаптера compose f gx

в простейшем композиционном адаптере результаты выполнения одной унарной операции становятся входными данными для другой унарной операции. Иначе говоря, этот адаптер просто обеспечивает вложенный вызов двух унарных объектов функций. Он понадобится для формулировки условий тина «прибавить 10 и умножить на 4».

Возможная реализация адаптера compose f gx (в реализации SGI используется имя composel) выглядит так:

fo/composell.hpp #inc1ude <funct1onal>

/* Класс композиционного адаптера cofTipose f gx */

template <class OPl. class 0P2> class compose f gx t : public std::unary function<typename 0P2:;argument type,

typename OPl::result type>

private:

OPl opl: Вычисление: opl(op2Cx)) 0P2 op2: public: Конструктор

compose f gx t(const 0P1& ol. const 0P2& o2) : oplCol). op2(o2) (

Вызов функции typename OPl::result type

operatorOCconst typename 0P2: :argument type& x) const { return opUop2(x)):



0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 [ 98 ] 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239