Форум программистов, компьютерный форум, киберфорум
IGPIGP
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  

Указатель на функцию и функтор

Запись от IGPIGP размещена 05.07.2016 в 22:30
Показов 4880 Комментарии 0

Недавно потребовалось передать функтор туда, где ожидается указатель на функцию. Удивительно, но сходу не получается. Оказывается, именем объекта функтора нельзя инициализировать указатель на функцию, несмотря на полностью совпадающие типы возврата и списки формальных параметров.
Прямых указаний в интернете по запросам содержащим "функтор" и "указатель на функцию" найти не удалось, хотя информации и по функторам и по указателям достаточно много. Наиболее близкой для решения задачи, мне показалась информация от AlenaCpp:
http://alenacpp.blogspot.com/2... -post.html
Там при упоминании функторов есть вот такой шаблончик
C++
1
2
3
4
5
6
7
template <class Fun>
void foo(Fun f)
{
  //...
  f();
  //...
}
Продемонстрировать результат моих размышлений на простом и искусственном (надуманном) примере можно бы так:
C++
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
#include <iostream>
using namespace std;
 
struct Call_back_class
{
 
int a;
int b;
 
Call_back_class(int a_, int b_)
:a(a_), b(b_)
{}
 
Call_back_class(const Call_back_class &rhs)
:a(rhs.a), b(rhs.b), calc_result(rhs.calc_result)
{}
 
int (*calc_result)(Call_back_class &);
 
int calc(){return (*calc_result)(*this);}
 
};
 
template< typename Arg, typename T>
int foo(Arg &n)
{
T f;
return f(n);
}
 
int main(int argc, char* argv[])
{
 
Call_back_class cb(123, 456);
 
struct Plus
{
int operator()(const Call_back_class &cbck_){ return cbck_.a + cbck_.b ;}
};
 
int (*calc_result)(Call_back_class &) = foo<Call_back_class, Plus>;
cb.calc_result=calc_result;
cout<<cb.calc()<<endl;//579
cout<<endl;
 
struct Minus
{
int operator()(const Call_back_class &cbck_){ return cbck_.a - cbck_.b ;}
};
 
cb.calc_result= foo<Call_back_class, Minus>;
cout<<cb.calc()<<endl;//-ззз
cout<<endl;
 
struct Multiply
{
int operator()(const Call_back_class &cbck_){ return cbck_.a * cbck_.b ;}
};
 
cb.calc_result= foo<Call_back_class, Multiply>;
cout<<cb.calc()<<endl;//56088
cout<<endl;
 
system("pause");
return 0;
}

Указатели на функции, построенные как шаблонные обёртки функторов, могут пригодиться не только для реализации обратных вызовов. Вот что удалось выяснить, в случае использования функтора, как предиката (один из самых частых вариантов).
Вот тут, я нашёл интересный пример с размышлением о том, как дорого по производительности может обойтись функтор-предикат, переданный алгоритму сортировки.
https://habrahabr.ru/post/234215/
Речь идёт о конструировании объектов. Вывод о том, что на каждый акт сравнения запускается полтора конструктора не радует.
Однако применив фокус с указателем на функцию запускающую функтор можно сократить количество конструкторов на треть. А если усовершенствовать шаблон снабдив его статическим объектом функтора, то потребуется всего один конструктор независимо от количества сравнений(!!):
C++
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
#include <iostream>
#include <vector>
#include <algorithm>
 
using namespace std;
 
class Compare
{
public:
    
    Compare()
    {
      cout<<"Compare::Compare()"<<endl;
    }
 
    Compare(const Compare& compare)
    {
      cout<<"Compare::Compare(const Compare& )"<<endl;
    }
 
    ~Compare()
    {
      cout<<"Compare::~Compare()"<<endl;
    }
  
    bool operator() (int v1, int v2)
    {
      cout<<"compare "<<v1<<" "<<v2<<endl;
      return v1 < v2;
    }
};
 
template< typename Arg, typename T>
bool foo(Arg m, Arg n )
{
T f;
return f(m, n);
}
 
template< typename Arg, typename T>
bool fo(Arg m, Arg n )
{
static T f=T();
return f(m, n);
}
 
int main()
{
    vector<int> mas;
 
    for( int k = 0; k <= 3; k++ )    
        mas.push_back( rand() );
    for( int k = 0; k <= 3; k++ )cout << mas[k]<<" ";    
    cout << endl;
 
    //sort( mas.begin(), mas.end(), Compare() );//раскомментируйте этот кошмар...
    //11 конструкторов и деструкторов
 
    //bool (*comp)(int, int)= foo<int, Compare>;//это немного лучше -
    //sort( mas.begin(), mas.end(), *comp );//8 шт. - на каждое сравнение по одному конструктору/деструктору 
 
    bool (*cmp)(int, int)= fo<int, Compare>;//а тут всего один конструктор! :)
    sort( mas.begin(), mas.end(), *cmp );
 
    for( int k = 0; k <= 3; k++ )cout << mas[k]<<" ";    
    cout << endl;
    system("pause");
    return 0;
}
раскомментируйте закоментированные фрагменты по очереди, закомментировав остальные и посмотрите разницу.
Размещено в Без категории
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Всего комментариев 0
Комментарии
 
Новые блоги и статьи
Был там один разговор по поводу свободы в материальном мире.
kumehtar 19.08.2026
Суть: рассматривается живое существо, оказавшееся внутри довольно странной системы (этого мира) и пытающееся обустроить в ней свой кусок пространства. Жизнь действительно предъявляет каждому. . .
Когда логика программы не спасает от человеческих ошибок
Maks 18.08.2026
В последнее время всё чаще и чаще сталкиваюсь с таким явлением, как абсолютная невнимательность (или глупость) пользователей. Проявляется это чаще всего на работе в коллективе. Допустим, человек с. . .
Лето уходит
kumehtar 17.08.2026
Мысли в слух
kumehtar 17.08.2026
Забавно, насколько сейчас стала доступна информация. Например о магии, духовном развитии, медитациях, и других подобных направлениях, ранее зачастую тайных, передаваемых от учителя к ученику. Хотя. . .
Перемещение строк из ТЧ в другой документ с учетом текущего пробега
Maks 17.08.2026
Реализация из решения ниже выполнена на примере нетипового документа "Автозапчасти", с ТЧ "Шины". За основу взят алгоритм отсюда: https:/ / www. cyberforum. ru/ blogs/ 359708/ 10838. html Задача: . . .
Саморегулирующийся социальный контракт для сервера cross-section.
Hrethgir 14.08.2026
С кодом конечно таких глубоких размышлений пока не было, впрочем я уже привык к алгоритмизации. Суть предмета записи: снова в диалоге с нейросетью (я взял пока себе ник для учётки админа - Rector). . . .
Часы электронные
Uhbif79 12.08.2026
Выкладываю программу часов. Программа позволяет: 1. Использовать системное время и дату, 2. Есть возможность вводить время и дату вручную. 3. Реализованы 2 будильника: начало и конец рабочего дня. . . .
Часы с будильником на основе класса QLCDNumber
Uhbif79 12.08.2026
Всем добрый день, выкладываю программу часов с будильником на основе класса QLCDNumber. Здесь я пробовал самостоятельно создавал классы, впервые столкнулся с видимостью переменной одного класса из. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru