Что такое функтор???
От: Amon-RA  
Дата: 18.11.03 06:45
Оценка:
привет все.
Люди, не объясните популярно, что такое функтор. Спасибо
Re: Что такое функтор???
От: Bell Россия  
Дата: 18.11.03 06:54
Оценка:
Здравствуйте, Amon-RA, Вы писали:

AR>привет все.

AR>Люди, не объясните популярно, что такое функтор. Спасибо

Это объект класса, имеющего переопределенный оператор operator ()


class func
{
   int n_;
public:
   func(int n) : n_(n) {}
   bool operator() (int n) { return n == n_; }
};

...

func functor;
Любите книгу — источник знаний (с) М.Горький
Re[2]: Что такое функтор???
От: Amon-RA  
Дата: 18.11.03 06:56
Оценка:
Здравствуйте, Bell, Вы писали:

B>Здравствуйте, Amon-RA, Вы писали:


AR>>привет все.

AR>>Люди, не объясните популярно, что такое функтор. Спасибо

B>Это объект класса, имеющего переопределенный оператор operator ()



B>
B>class func
B>{
B>   int n_;
B>public:
B>   func(int n) : n_(n) {}
B>   bool operator() (int n) { return n == n_; }
B>};

B>...

B>func functor;
B>


И зачем оно надо и зачем обзывать его по особенному?
Re[3]: Что такое функтор???
От: LaptevVV Россия  
Дата: 18.11.03 06:59
Оценка:
Здравствуйте, Amon-RA, Вы писали:

AR>И зачем оно надо и зачем обзывать его по особенному?


А затем, чтобы заменить указатели на функции при обработке сложных структур данных.
С указателями, как ты понимаешь, хлопот больше, чем выгод.
А функтор — это ОБЪЕКТ, который можно передавать и по значению. Инкапсуляция и надежность программ повышаются.
А еще — можно состояния хранить — полей-то можно определить какие хочешь.
Если более подробно, то надо в книжках читать.
На эту тему много написано.
Хотя бы у Александреску.
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Re: Что такое функтор???
От: Андрей Тарасевич Беларусь  
Дата: 18.11.03 08:10
Оценка: 35 (2) +1
Здравствуйте, Amon-RA, Вы писали:

AR>привет все.

AR>Люди, не объясните популярно, что такое функтор. Спасибо

Функтор — собирательный термин, который обозначает все виды сущностей в С++, к которым применим оператор вызова функции — '()'. Функторы сразу делятся на два подкласса — 1) обыкновенные функции (указатели на обыкновенные функции) к которым применяется встроенный оператор '()' и 2) функциональные объекты — объекты классов с перегруженным оператором '()'.

Иногда под термином 'функтор' продразумевают только функциональные объекты. Это, строго говоря, некорректное употребление данного термина. Обычные функции и указатели на них тоже являются частными случаями функторов.
Best regards,
Андрей Тарасевич
Re[2]: Что такое функтор???
От: Аноним  
Дата: 18.11.03 08:20
Оценка:
А если есть оператор преобразования в указатель на функцию или ссылку на указатель на функцию, объект такого класса можно назвать функтором?
Re[2]: Что такое функтор???
От: Кодт Россия  
Дата: 18.11.03 09:20
Оценка:
Здравствуйте, Андрей Тарасевич, Вы писали:

АТ>Функтор — собирательный термин, который обозначает все виды сущностей в С++, к которым применим оператор вызова функции — '()'. Функторы сразу делятся на два подкласса — 1) обыкновенные функции (указатели на обыкновенные функции) к которым применяется встроенный оператор '()' и 2) функциональные объекты — объекты классов с перегруженным оператором '()'.


И еще связки (closure) объект.метод.

Поскольку в С++ (а не в диалекте Borland C++ Builder) такая сущность не существует отдельно от ее выполнения — то ее эмулируют, например, функциональным объектом-оберткой.

Криво выразился Андрей, поправь пожалуйста, если надо.
Перекуём баги на фичи!
Re[4]: Что такое функтор???
От: WolfHound  
Дата: 18.11.03 09:55
Оценка: -4
Здравствуйте, LaptevVV, Вы писали:

LVV>А затем, чтобы заменить указатели на функции при обработке сложных структур данных.

Нафига?
LVV>С указателями, как ты понимаешь, хлопот больше, чем выгод.
С указателями на ФУНКЦИИ? Нука просвети.
LVV>А функтор — это ОБЪЕКТ, который можно передавать и по значению.
Указатель на функцию тоже.
LVV>Инкапсуляция и надежность программ повышаются.
Чем?
LVV>А еще — можно состояния хранить — полей-то можно определить какие хочешь.
Функтор с сотоянием? Чему ты народ учишь...
Это такаяже кривь как и(НИ КОГДА ТАК НЕ ДЕЛАЙТЕ)
int fibonacci()
{
    static int x1=1;
    static int x2=1;
    int x3=x1+x2;
    x1=x2;
    x2=x3;
    retunr x3;
}

Изврат правда. Функтор с сотоянием ни чем не отличается. Вернее это и есть функтор с состоянием.
LVV>Если более подробно, то надо в книжках читать.
LVV>На эту тему много написано.
LVV>Хотя бы у Александреску.
Почитать можно, а вот использовать не стоит. Лучше boost::function.
... << RSDN@Home 1.1 beta 2 >>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[5]: Что такое функтор???
От: PM  
Дата: 18.11.03 10:23
Оценка:
Здраствуйте, WolfHound. Вы писали:

хъ
LVV>> А еще — можно состояния хранить — полей-то можно определить какие
LVV>> хочешь.
W> Функтор с сотоянием? Чему ты народ учишь...
W> Это такаяже кривь как и(НИ КОГДА ТАК НЕ ДЕЛАЙТЕ)
W>
 W> int fibonacci()
 W> {
 W>  static int x1=1;
 W>  static int x2=1;
 W>  int x3=x1+x2;
 W>  x1=x2;
 W>  x2=x3;
 W>  retunr x3;
 W> }
 W>

W> Изврат правда. Функтор с сотоянием ни чем не отличается. Вернее это и
W> есть функтор с состоянием.
Извиняюсь, что влез в дискуссию, но я бы не стал так категорично утверждать, что функтор-класс с состоянием полный отстой
Приведенный выше пример, конечно, показывает как не надо писать. Но иногда просто необходимо знать состояние предыдущего вызова:
/// Accumulate characters until terminator char doubled
class chars_accumulator2
{
public:
 chars_accumulator2(char terminator) : term_(terminator), num_terms_(0) {}
 bool operator()(char ch)
 {
  if ( 2 == num_terms_ ) 
  {
    result.erase( result.end()-2, result.end() );
    return false;
  }
  num_terms_ = ( term_ == ch )? num_terms_ + 1 : 0;
  result.push_back(ch);
  return true;
 }
 std::string result;
private:
 char term_;
 size_t num_terms_;
};

...
std::string s("blablazzbla");
chars_accumulator2 camm2('z');
for (std::string::iterator it = s.begin(); it != s.end(); ++it)
{
    if ( !camm2(*it) ) break;
}

assert ( camm2.result == "blabla");
Posted via RSDN NNTP Server 1.7 "Bedlam"
Re[5]: Что такое функтор???
От: Bell Россия  
Дата: 18.11.03 10:28
Оценка: 2 (2)
Здравствуйте, WolfHound, Вы писали:

Ну зачем же так сплеча

LVV>>А затем, чтобы заменить указатели на функции при обработке сложных структур данных.

WH>Нафига?
Ну хотя бы для повышения эффективности (что ИМХО является очень весомым фактором). Дело в том, что компилятор обычно не "инлайнит" вызов функции через указатель, а вот вызов переопределенного operator() у объекта — легко. Подробности у Майерса в "Effective STL", совет 46.

LVV>>А еще — можно состояния хранить — полей-то можно определить какие хочешь.

WH>Функтор с сотоянием? Чему ты народ учишь...
WH>Это такаяже кривь как и(НИ КОГДА ТАК НЕ ДЕЛАЙТЕ)

Функторы бывают разные. Что ты скажешь, например, о таком?
class in_range
{
   int begin_, end_;
public:
   in_range(int begin, int end) : begin_(begin), end_(end) {}
   bool operator () (int n) { return n >= begin_ && n < end; }
};

?

Или о стандартных биндерах? Или о семействе mem_fun?
Думаю, ты изменишь свое мнение о функторах с сотоянием.
Любите книгу — источник знаний (с) М.Горький
Re[5]: Что такое функтор???
От: LaptevVV Россия  
Дата: 18.11.03 10:42
Оценка:
Здравствуйте, WolfHound, Вы писали:

LVV>>А затем, чтобы заменить указатели на функции при обработке сложных структур данных.

WH>Нафига?
Ага, а итераторы (хоть это и не функцторы) нафига придумали. Обходились бы указателями!
LVV>>С указателями, как ты понимаешь, хлопот больше, чем выгод.
WH>С указателями на ФУНКЦИИ? Нука просвети.
Потому что указатели. Типовые преобразования сделать — как два байта переслать. Функторы просто так не преобразуешь.
Хотя для реализации таблицы виртуальных функций именно указатели на функции используются, но ведь не зря их спрятали — уровень программирования повышается.
LVV>>А функтор — это ОБЪЕКТ, который можно передавать и по значению.
WH>Указатель на функцию тоже.
Ну да, он так и передается. Просто внутри функции, которая получила указатель на функцию можно через преобразование типов вызвать практически ЛЮБУЮ другую. С функтором так просто не получится.
LVV>>Инкапсуляция и надежность программ повышаются.
WH>Чем?
Именно из-за объектной обертки.
WH>Почитать можно, а вот использовать не стоит. Лучше boost::function.
Нужно читать. А использовать — при необходимости.
Что-то уж больно воинственно
Давайте жить дружно!
Хочешь быть счастливым — будь им!
Без булдырабыз!!!
Re[5]: Что такое функтор???
От: Кодт Россия  
Дата: 18.11.03 11:45
Оценка: 1 (1)
Здравствуйте, WolfHound, Вы писали:

LVV>>А еще — можно состояния хранить — полей-то можно определить какие хочешь.

WH>Функтор с сотоянием? Чему ты народ учишь...

Функтор с состоянием — это разновидность функции с побочным эффектом.
Пример:
int fibo(int n)
{
  int f;
  ... вычисляем ...

  cout << "F(" << n << ")" << f << endl; // побочный эффект
  return f;
}

int fibo_once(int n)
{
  static map<int,int> fn;
  map<int,int>::const_iterator it = fn.find(n);
  if(it == fn.end())
  {
    int f = fibo(n);
    fn[n] = f; // еще один побочный эффект
    return f;
  }
  else return it->second;
}

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

Другое практичное применение функторов с состояниями: callback для разнообразных enum-функций.
Например, посмотри, как делается перечисление шрифтов в виндовозе. В callback-функции ты запоминаешь каждый присланный шрифт, а по выходе из api-шного вызова — берешь полученную коллекцию и делаешь с ней что хочешь.
Перекуём баги на фичи!
Re[5]: Что такое функтор???
От: Юнусов Булат Россия  
Дата: 18.11.03 12:11
Оценка:
Здравствуйте, WolfHound, Вы писали:

WH>Функтор с сотоянием? Чему ты народ учишь...

WH>Это такаяже кривь как и(НИ КОГДА ТАК НЕ ДЕЛАЙТЕ)
WH>
WH>int fibonacci()
...
WH>

WH>Изврат правда. Функтор с сотоянием ни чем не отличается. Вернее это и есть функтор с состоянием.

Неа, это "одноразовый" функтор какой то

Функторы реинкарнируются, а функции нет.
int fibonacci()
{
    static int x1 = 1;
    static int x2 = 1;
    int x3 = x1 + x2;
    x1 = x2;
    x2 = x3;
    return x3;
}

struct fibo
{
    int x1, x2;
    
    fibo() : x1(1), x2(1)
    {
    }
    
    int operator()()
    {
        int x3 = x1 + x2;
        x1 = x2;
        x2 = x3;
        return x3;
    }
};

int main(int argc, char* argv[])
{
    std::generate_n(std::ostream_iterator<int>(std::cout, "\n"), 5, fibonacci);
    std::generate_n(std::ostream_iterator<int>(std::cout, "\n"), 5, fibonacci);
    
    std::cout << std::endl;
    
    std::generate_n(std::ostream_iterator<int>(std::cout, "\n"), 5, fibo());
    std::generate_n(std::ostream_iterator<int>(std::cout, "\n"), 5, fibo());
    
    return 0;
}
Re[6]: Что такое функтор???
От: WolfHound  
Дата: 18.11.03 14:56
Оценка:
Здравствуйте, PM, Вы писали:

PM>Извиняюсь, что влез в дискуссию, но я бы не стал так категорично утверждать, что функтор-класс с состоянием полный отстой

А я бы стал. Особенно когда дело касается тех кто плохо понимает что делает.
PM>Приведенный выше пример, конечно, показывает как не надо писать. Но иногда просто необходимо знать состояние предыдущего вызова:
Спасибо! Великолепный пример того как не надо делать. Не знаю как другие а я бы долго думал что тут происходит. И скорей всего бы не понял без заглядывания в хидер. Болие того у тебя там ошибка. Введи такую строку "blablazz" результат тебя удивит.
В данном случае нужен не функтор, а алгоритм
Примерно такой
template
    <class input_iter
    ,class output_iter
    >
void repeat_until_terminator_doubled
    (input_iter begin
    ,input_iter end
    ,output_iter out
    ,typename std::iterator_traits<input_iter>::value_type terminator
    )
{
    typedef typename std::iterator_traits<input_iter>::value_type value_type;
    if(begin==end)return;
    value_type val[2];
    bool flag=false;//Используем свойства bool'ов false==0 true==1
    val[flag]=*begin;
    while(true)
    {
        ++begin;
        if(begin==end)
        {
            *out=val[flag];
            return;
        }
        flag=!flag;
        val[flag]=*begin;
        if(val[0]==val[1])
            return;
        *out=val[!flag];
        ++out;
    }
};

Использование
    std::string str("asdasfzasdzasfdzzaas");
    std::string res;
    repeat_until_terminator_doubled(str.begin(), str.end(), std::back_inserter(res), 'z');

или
    repeat_until_terminator_doubled
        (std::istream_iterator<char>(std::cin)
        ,std::istream_iterator<char>()
        ,std::ostream_iterator<char>(std::cout)
        ,'z'
        );

std::cin не очень удачный источник ибо у него нет конца (возьми ifstream) цикл будет повторятся пока не введешь zz но это не суть важно.
Главное это решение болие понятно и универсально чем твое.
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[7]: Что такое функтор???
От: WolfHound  
Дата: 18.11.03 15:04
Оценка:
Здравствуйте, WolfHound, Вы писали:

fix
заменить
        if(val[0]==val[1])
            return;

на
        if(val[0]==terminator&&val[1]==terminator)
            return;
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[6]: Что такое функтор???
От: WolfHound  
Дата: 18.11.03 15:07
Оценка:
Здравствуйте, Bell, Вы писали:

B>Функторы бывают разные. Что ты скажешь, например, о таком?

хъ
B>Или о стандартных биндерах? Или о семействе mem_fun?
B>Думаю, ты изменишь свое мнение о функторах с сотоянием.
Следуя данной терминологии ВСЕ функторы (в том числе и функции) являются функторами с состоянием.
В моем понимании функтор с состоянием это такой функтор который помнит что с ним было при прошлом вызове. in_range этим не страдает.
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[6]: Что такое функтор???
От: WolfHound  
Дата: 18.11.03 15:13
Оценка:
Здравствуйте, LaptevVV, Вы писали:

LVV>>>А затем, чтобы заменить указатели на функции при обработке сложных структур данных.

WH>>Нафига?
LVV>Ага, а итераторы (хоть это и не функцторы) нафига придумали. Обходились бы указателями!
А они тут причем?
LVV>>>С указателями, как ты понимаешь, хлопот больше, чем выгод.
WH>>С указателями на ФУНКЦИИ? Нука просвети.
LVV>Потому что указатели. Типовые преобразования сделать — как два байта переслать. Функторы просто так не преобразуешь.
Код в студию.(только без reinterpret_cast и c-style cast)

LVV>>>Инкапсуляция и надежность программ повышаются.

WH>>Чем?
LVV>Именно из-за объектной обертки.
Не понял что тут инкапсулировать?
int (*fn_ptr)(int);
Ы?

WH>>Почитать можно, а вот использовать не стоит. Лучше boost::function.

LVV>Нужно читать. А использовать — при необходимости.
Loki это учебная библиотека. И относится к ней надо соответствующи.
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[6]: Что такое функтор???
От: WolfHound  
Дата: 18.11.03 15:34
Оценка:
Здравствуйте, Кодт, Вы писали:

И где тут запоминают состояние функции?
К>
К>int fibo(int n)
К>{
К>  int f;
К>  ... вычисляем ...

К>  cout << "F(" << n << ")" << f << endl; // побочный эффект
К>  return f;
К>}
К>

А вто так не делать однозначно
К>
К>int fibo_once(int n)
К>{
К>  static map<int,int> fn;
К>  map<int,int>::const_iterator it = fn.find(n);
К>  if(it == fn.end())
К>  {
К>    int f = fibo(n);
К>    fn[n] = f; // еще один побочный эффект
К>    return f;
К>  }
К>  else return it->second;
К>}
К>

К>Тоже, скажешь, так не делать? Тогда получим чистый функциональный язык, в котором любое выражение есть константа.
Да скажу.
А теперь в твою fibo_one начали передавать значения 1000, 999...1

К>Другое практичное применение функторов с состояниями: callback для разнообразных enum-функций.

К>Например, посмотри, как делается перечисление шрифтов в виндовозе. В callback-функции ты запоминаешь каждый присланный шрифт, а по выходе из api-шного вызова — берешь полученную коллекцию и делаешь с ней что хочешь.
Те ты хочешь сказать что каждое решение МС образцом для подражания?
Ну например посмотри на FindFirstFile. Ы? Мне он нравится больше ибо на раз вписывается в концепцию input iterator.
Те можно написать примерно так
    std::for_each
        (find_file_iterator("c:\\*.*")
        ,find_file_iterator()
        ,print_file_info
        );
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[6]: Что такое функтор???
От: WolfHound  
Дата: 18.11.03 15:36
Оценка:
Здравствуйте, Юнусов Булат, Вы писали:

ЮБ>Неа, это "одноразовый" функтор какой то


ЮБ>Функторы реинкарнируются, а функции нет.

хъ
Генерация последовательности пожалуй единственное разумное применение. Но на столько редкое что я о нем забыл .
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[7]: Что такое функтор???
От: FreshMeat Россия http://www.rsdn.org
Дата: 18.11.03 16:17
Оценка: 2 (1)
Здравствуйте, WolfHound, Вы писали:

WH>Здравствуйте, Bell, Вы писали:


B>>Функторы бывают разные. Что ты скажешь, например, о таком?

WH>хъ


B>>Или о стандартных биндерах? Или о семействе mem_fun?

B>>Думаю, ты изменишь свое мнение о функторах с сотоянием.
WH>Следуя данной терминологии ВСЕ функторы (в том числе и функции) являются функторами с состоянием.
WH>В моем понимании функтор с состоянием это такой функтор который помнит что с ним было при прошлом вызове. in_range этим не страдает.
Пример был очень хороший. После того как его увидел, не стал постить свой (менее выразительный и дублирующий уже сказанное), но если тебя не убедили, держи вдогонку:
задача — отсортировать точки по увеличению расстояния от заданной
struct less_dist : std::binary_function<bool, point2, point2>
{
    explicit less_dist( const point2& base ) : m_base( base ) {}
    bool operator()( const point2& p0, const point2& p1 )
    {
        return sqr_dist( m_base, p0 ) < sqr_dist( m_base, p1 );
    }
private:
    const point2 m_base;
};
...
// сортируем элементы контейнера по расстоянию от точки
std::sort( v.begin(), v.end(), less_dist( point2(0, 0) ) );


Насчет состояний... Если я правильно понял, то под состоянием, ты понимаешь значения статических свойств класса. Это несколько расходится с формулировкой стандарта.
Definitions
17.1.10 Object state
The current value of all nonstatic class members of an object. The state of an object can be obtained by using one or more observer functions
Хорошо там, где мы есть! :)
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.