Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
STL5 / lab8-functors / lab8-STL-functor.doc
Скачиваний:
9
Добавлен:
10.04.2015
Размер:
259.07 Кб
Скачать

Адаптеры

Еще одной категорией специализированных функторов являются адаптеры, их задача заключается в адаптации к требованиям STLфункций и методов классов.

Адаптеры функций

Как уже было описано ранее для применения отрицателя (а также связывателя) необходимо, чтобы отрицаемый функтор был наследником unary_functionилиbinary_function, в которых определены имена типов используемые реализацией отрицателя. Однако если исходный предикат являетсяобычной функцией, а не объектом с перегруженнымoperator(), он не может быть наследником никакого класса, а также не может определить имена требуемых типов любым другим способом. Для адаптации таких случаев в стандартной библиотеке предусмотрены специальные объекты, основная задача, которых определить требуемые имена типов и вызвать в нужный момент указанную функцию через указатель:

template<class Arg, class Result>

class pointer_to_unary_function: public unary_function<Arg, Result>

{

public:

explicit pointer_to_unary_function(Result (__cdecl * x)(Arg));

Result operator()(Arg x) const;

};

template<class Arg1, class Arg2, class Result>

class pointer_to_binary_function: public binary_function<Arg1, Arg2, Result>

{

public:

explicit pointer_to_binary_function(Result (__cdecl * x)(Arg1,Arg2));

Result operator()(Arg1 x, Arg2 y) const;

};

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

Чтобы понять принцип работы адаптера, рассмотрим их возможную реализацию:

template<class Arg, class Result>

class pointer_to_unary_function: public unary_function<Arg, Result>

{

public:

explicit pointer_to_unary_function(Result (__cdecl * x)(Arg))

:Function(x) {}

Result operator()(Arg x) const

{

return Function(x);

}

protected:

Result (__cdecl * Function)(Arg);

};

template<class Arg1, class Arg2, class Result>

class pointer_to_binary_function: public binary_function<Arg1, Arg2, Result>

{

public:

explicit pointer_to_binary_function(Result (__cdecl * x)(Arg1,Arg2))

: Function(x) {}

Result operator()(Arg1 x, Arg2 y) const

{

return Function(x,y);

}

protected:

(__cdecl * Function)(Arg1,Arg2);

};

Как видно реализация адаптера достаточно проста, конструктор сохраняет указатель на адаптируемую функцию, который используется, для переадресации вызова в момент вызова функтора.

Для адаптеров, как и для отрицателей, стандартная библиотека содержит вспомогательные функции, которые могут быть использованы для создания объектов адаптеров. Они позволяют использовать механизм выведения аргументов шаблонов для функции вместо явного указания аргументов шаблонов для классов pointer_to_unary_functionиpointer_to_binary_function

template<class Arg, class Result>

pointer_to_unary_function<Arg, Result> ptr_fun(Result (*f)(Arg))

{

return pointer_to_unary_function<Arg,Result>(f);

}

template<class Arg1, class Arg2, class Result>

pointer_to_binary_function<Arg1, Arg2, Result> ptr_fun(Result (*f)(Arg1, Arg2))

{

return pointer_to_binary_function<Arg1,Arg2,Result>(f);

}

Изменим предыдущий пример для случая, когда предикат IsEvenявляется функцией, а не функтором:

. . .

bool IsEven(int arg)

{

return (arg % 2) == 0;

}

int main (int, char**)

{

. . .

// Следующий вариант приводит к ошибке компиляции, IsEven не определяет

// требуемых типов

//v.erase(remove_if(v.begin(),v.end(),not1(IsEven)),v.end());

// Правильный вариант

v.erase(remove_if(v.begin(),v.end(),not1(ptr_fun(IsEven))),v.end());

// Тоже правильный вариант, но предыдущий удобнее

v.erase(remove_if(v.begin(),v.end(),

not1(pointer_to_unary_function<int,bool>(IsEven))),

v.end());

. . .

}

Соседние файлы в папке lab8-functors