Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > Функтор


Автор: knut 14.12.2006, 16:12
Добрый день.Меня мучает вопрос касающий функторов.
1.Вот если главная задаяча функтора это соxраниние даныx между вызовами функции то не получиться это все зделать с помощью статическиx переменныx?(Можно реальный пример с использ.функторов или сылку где можно прочитать)В чем фишка функтора?
2.Аналог делегата в с++.Есть вообще связь между делегатом и функтором?
Вообще скинте сылки где прочитать буду признателен smile

Автор: JackYF 14.12.2006, 16:53
Аналог делегата - указатель на функцию.
Подробнее - гугл в помощь.

Одна из главных задач функтора - возможность передачи функции как параметра шаблона.
Для этого в классе перегружается operator() и выходит функтор.

А сохранение переменных между вызовами - делай как хочешь. Но лучше нестатически, потому что у тебя могут сосуществовать несколько разных экземпляров функтора одновременно.

Автор: knut 14.12.2006, 17:18
Цитата

Одна из главных задач функтора - возможность передачи функции как параметра шаблона.
Для этого в классе перегружается operator() и выходит функтор.

т.е экземпляр класса ведет себя как функция я правельно понял?если да то что это нам дает?()
можем писать так
Код

class Test
{
   private: 
              int i;
   int operator(int a,int b)
     {
         return i+a+b;
     } 
}
Test ob;
cout<<ob(5,5);

Автор: zabivator 14.12.2006, 17:33
knut, да, именно так.
Вообще говоря, тема функторов очень обширна... Я прочитал когда твой пост думал отвечать-не отвечать, в итоге забил =) Читай, например, Александреску, или новые сложные от Саттера - там эта тема исчерпывающим образом раскрыта.

Автор: JackYF 14.12.2006, 18:02
Цитата(knut @  14.12.2006,  17:18 Найти цитируемый пост)
если да то что это нам дает?()


Передавать как параметр шаблона, например, в стандартные контейнеры STL(допустим, функцию сравнения двух элементов).



Автор: Любитель 14.12.2006, 18:08
Цитата(JackYF @  14.12.2006,  16:53 Найти цитируемый пост)
Аналог делегата - указатель на функцию

Не совсем. Не помню, как в С# 1.0, но уже во второй версии, можно делать делегаты прямо в коде - по сути лямбда-функции. В плюсах для этого нет языковой поддержки (я надеюсь - и не будет, это не в стиле плюсов), но есть ФП в стиле STL, и (как его развитие) - в стиле буста (да, да и ещё раз да).
std::bind1st, std::bind2nd, boost::bind, boost::lambda, boost::signals, boost::function - это приплющенное функциональное программирование. Собственно функторы - это основа ФП в плюсах. Биндить обычные функции (во что?), генерить лямбды (что мы получим?) и прочее - как сие представить без функторов.

В этом мне сильно не нравится кутешные сигнал/слоты, которые реализуется как таблицы строка => казатель на функцию. Очень часто мне бы хотелось рантайм генерацию слотов (как объектов). boost::signals явно рулит, но не доделан:
1. непотокобезопасный
2. нет возможности разделения на коннект слотов, и инициация сигнала (часто коннектить может кто угодно, а инициация - прайват или протектед).

Автор: zabivator 14.12.2006, 18:12
Любитель, а в чем именно проявляется его непотокобезопасность? Я это читал в документации, но не догнал.

Автор: JackYF 14.12.2006, 18:17
Цитата(Любитель @  14.12.2006,  18:08 Найти цитируемый пост)
Не совсем.

Я же сказал - "аналог", а не то же самое smile

Автор: knut 14.12.2006, 18:28
JackYF
Цитата

Передавать как параметр шаблона, например, в стандартные контейнеры STL(допустим, функцию сравнения двух элементов).

а что это без функтора нельзя зделать?

Автор: Daevaorn 14.12.2006, 18:33
Цитата(knut @  14.12.2006,  19:28 Найти цитируемый пост)
а что это без функтора нельзя зделать? 

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

Автор: JackYF 14.12.2006, 18:33
В большинстве ситуаций с STL - контейнерами - да.

Код

template <class _Key, class _Compare, class _Alloc>
class map;


Здесь Compare - обязательно класс. Функция - это не класс, поэтому ты можешь передать в шаблон только функтор.

Автор: Любитель 14.12.2006, 18:47
Цитата(zabivator @  14.12.2006,  18:12 Найти цитируемый пост)
Любитель, а в чем именно проявляется его непотокобезопасность?

Если не ошибаюсь - одновременный коннект слотов к одному сигналу. Дома посмотрю поподробнее.

ЗЫ. Может попробовать исправить (если это будет достаточно реально)?


Цитата(JackYF @  14.12.2006,  18:17 Найти цитируемый пост)
Я же сказал - "аналог", а не то же самое

Просто фраза "функтор - аналог делегата" пожалуй даже точнее чем "указатель на функцию - аналог делегата". Хотя и это не корректно. Лучше аналогий не проводить (приплющенное ФП уникально по своей природе  smile )

Добавлено @ 18:51 
Цитата(JackYF @  14.12.2006,  18:33 Найти цитируемый пост)
Здесь Compare - обязательно класс. Функция - это не класс, поэтому ты можешь передать в шаблон только функтор

Ой, а ты проверял. В темплейтах class означает "тип". Указатель на функцию также имеет тип. Сие вполне будет работать. Ну скажем (сновываясь только на твоём коде):
Код

map<int, bool (), my_allocator> my_map;


Посмотри на boost::function (ожно в онлайне - чтобы не качать сию бесполезную вещь), параметр шаблона - класс функтора или тип указателя на функцию.

Автор: JackYF 14.12.2006, 19:11
Цитата(Любитель @  14.12.2006,  18:47 Найти цитируемый пост)
Посмотри на boost::function (ожно в онлайне - чтобы не качать сию бесполезную вещь)

Все иронизируешь... smile


Цитата(Любитель @  14.12.2006,  18:47 Найти цитируемый пост)
map<int, bool (), my_allocator> my_map;

Цитата(Любитель @  14.12.2006,  18:47 Найти цитируемый пост)
Ой, а ты проверял.

А ты? Сие не только не будет работать, оно даже не откомпилируется.
(Вообще, я там раньше имел, конечно же, ввиду set, но это не суть важно).

GCC: 
error: invalid cast to function type `bool ()()'

Так-то.

Добавлено @ 19:16 
Я против boost::function ничего не имею... Но мне пока она не была нужна.

Автор: Любитель 15.12.2006, 11:04
JackYF, не внимательно читаем. Начинаю цитировать самого себя:
Цитата(Любитель @  14.12.2006,  18:47 Найти цитируемый пост)
сновываясь только на твоём коде

сновываясь == основываясь
То есть всё что мы знали о map - твоё обявление. Я не думал (или не хотел думать) о std::map.
Хотя соглашусь, для совместимости с функторами надо было написать так (использовать тип указателя на функцию, а не функции - как я написал):
Код

map<int, bool (*) (int, int), my_allocator> my_map;

А то, что я сказал работает. При соответствующем объявлении класса map (усекаем до минимума):
Код

template <class Compare>
class test
{
public:
   test();
};

int main()
{
   test<bool ()> t;
}


Любой нормальный компилер проглотит. Здесь есть правда ошибка - ... логическая. Compare по идее должна что-то сравнивать, а уна сие не так.  smile 

И всё же можно добавить функцию для установки компаратора. Если мы пишем, как я написал ранее, то придётся добавить пару звёздочек (после Compare - в функции и в обяъвлении поля). Особо старательные могут написать обобщённый код (с boost::enable_if), чтобы воспринимались как функции, так и указатели на них (и совместимые по семантике вызова с последними функторы). Для простоты считаем, что мы всё же пишем test<bool (*)()> (подчёркиваю - сие явно не функтор). Можно написать сию (абсолютно бесполезную) вещь:
Код

public:
  void set_comparator(Compare cmp)
  { comparator = cmp; }

  bool result()
  { return comparator(); }

private:
  cmp;
};

bool f()
{ return true; // :) }

int main()
{
  test<bool (*)()> t;
  t.set_comparator(f);
  if (t.result())
    // ...
}


Замечу, что Compare не обязан возвращать bool, он должен к нему приводится.

Прикол в том, что f одновременно и указатель на функцию и сама функция. Интересен тот факт, что для функций-членов (по стандарту) однако наджо использовать амперсанд. ТАк уж есть.

По сабжу - повторюсь функтор нужен для ФП (функционального программирования). Если нитересно - могу напридумывать тривиальных примеров (не хочется зря писать - если не интересно). Я сипипишное ФП очень люблю, потому меня сия тема интересует.

Цитата(JackYF @  14.12.2006,  19:11 Найти цитируемый пост)
Все иронизируешь... 

В какой-то мере... Просто, когда я ещё в школе учился, жил в небольшом таком городке и сидел дома на диалапе smile , буст мне представлялся чем-то нереальным. Я это прекрасно помню. Поэтому я сказал просто тот факт, что это можно посмотреть в онлайне. Ну, доля тонкого намёка на противоречивость фразы "бесполезность буста" была. Но впрочем, я надеюсь, здесь она просто между делом (не говорить же про одно и то же в 10 темах  smile )

Добавлено @ 11:18 
ЗЫ коммент в f я зря поставил  smile 

Автор: knut 15.12.2006, 12:24
Цитата

По сабжу - повторюсь функтор нужен для ФП (функционального программирования). Если нитересно - могу напридумывать тривиальных примеров (не хочется зря писать - если не интересно). Я сипипишное ФП очень люблю, потому меня сия тема интересует

ну давайsmileтема отчасти и для этого создавалaсь smile

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)