30 / 47 / 19
Регистрация: 23.10.2014
Сообщений: 1,001
1

Передача функции параметром

05.01.2015, 17:29. Показов 1924. Ответов 9
Метки нет (Все метки)

первый раз с этим дело имею, вот хотел с std::function разобраться, делаю что то вроде:

C++
1
2
3
4
5
6
7
int func(int) { return 0; }
...
int func() { return 0; }
...
void f(std::function<int()> func) {}
...
f(func);
и вот тут то и подкарауливает ошибка, без перегрузки в принципе все работает, но с перегрузкой ошибка
error C2664: "void f(std::function<int (void)>)": невозможно преобразовать аргумент 1 из "overloaded-function" в "std::function<int (void)>"
то бишь он типа не знает какую подставить чтоли? но ведь в параметрах шаблона явно указано что функция без аргументов так чего он тупит? вобщем можно как то это разрулить? чтобы и с перегруженными работало?
__________________
Помощь в написании контрольных, курсовых и дипломных работ, диссертаций здесь
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
05.01.2015, 17:29
Ответы с готовыми решениями:

Передача объекта параметром и последующее изменение
Неразбериха с классами. Я создаю экземпляр класса,и далее указатель на него его передаю параметром...

Функции с символьным параметром
Надо контрольные работы закрыть, помогите пожалуйста Задание 1 Принять с клавиатуры символ....

Функции со строковым параметром
Здравствуйте. Никак не могу понять, для чего нужен string::size_type, size_t и прочее. Почему...

Ипользование const с указателем, параметром функции
Здравия желаю!:) Хотелось бы узнать, как можно работать с параметрами-указателями при работе...

9
267 / 170 / 40
Регистрация: 25.08.2014
Сообщений: 1,087
Записей в блоге: 1
05.01.2015, 17:41 2
Передавай как указатель на функцию, явно приводи к указателю на нужный тип.
Вообще у тебя не объявлен тип-прототип для функции func.
0
30 / 47 / 19
Регистрация: 23.10.2014
Сообщений: 1,001
05.01.2015, 17:45  [ТС] 3
Цитата Сообщение от Enno Посмотреть сообщение
Передавай как указатель на функцию, явно приводи к указателю на нужный тип.
а чем std::function то не устраивает? чай не managed C, плюсы все же, значит надо пользоваться преимуществами... да и с указателями вызов затрудняется...
Цитата Сообщение от Enno Посмотреть сообщение
Вообще у тебя не объявлен тип-прототип для функции func.
как это не объявлен, а выше что?
0
Эксперт С++
8719 / 4262 / 950
Регистрация: 15.11.2014
Сообщений: 9,668
05.01.2015, 17:53 4
C++
1
2
3
4
5
6
7
8
9
10
int func(int) { return 0; }
...
int func() { return 0; }
...
void f(std::function<int()> func) {} //<--- имя параметра совпадает с именем функции
          //не критично, но это не есть хороший стиль
...
 
f(func);  //<--- std::function туповат. 
// Ему нужно подсказывать сигнатуру перегруженной функции

http://rextester.com/LYE16587


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
#include <iostream>
#include <functional>
using namespace std;
 
#if defined(__GNUC__) || defined(__MINGW32__) || defined(__MINGW32__)
    #define dFUNCTION __PRETTY_FUNCTION__
#else
    #ifdef _MSC_VER
        #define dFUNCTION __FUNCSIG__
    #else
        #define dFUNCTION __FUNCTION__
    #endif
#endif
 
 
int func(int v) { cout << dFUNCTION << ": arg = "<< v<<'\n'; return 0; }
int func()      { cout << dFUNCTION << '\n'; return 0; }
 
 
typedef std::function<int()>
    Callback;
 
int func(const Callback& callback)
{ 
    cout << dFUNCTION << '\n'; 
    if(callback)
        return callback();
    return 0;
}
    
int main()
{
    std::cout << "Hello, world!\n";
    
    Callback f = static_cast<int(*)()>(&func);
    
    cout<<"---------------\n";
    func();
 
    cout<<"---------------\n";
    func(10);
 
    cout<<"---------------\n";
    func(f);
}
0
30 / 47 / 19
Регистрация: 23.10.2014
Сообщений: 1,001
05.01.2015, 18:14  [ТС] 5
Цитата Сообщение от hoggy Посмотреть сообщение
Callback f = static_cast<int(*)()>(&func);
вот в том то и дело хотелось бы обойтись без дополнительных объявлений если это возможно, просто подал название функции, ну может параметры функции или шаблона еще...
0
Эксперт С++
8719 / 4262 / 950
Регистрация: 15.11.2014
Сообщений: 9,668
05.01.2015, 19:32 6
http://rextester.com/IVJW56029

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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
#include <iostream>
#include <functional>
//#include <type_traits>
using namespace std;
 
#if defined(__GNUC__) || defined(__MINGW32__) || defined(__MINGW32__)
    #define dFUNCTION __PRETTY_FUNCTION__
#else
    #ifdef _MSC_VER
        #define dFUNCTION __FUNCSIG__
    #else
        #define dFUNCTION __FUNCTION__
    #endif
#endif
 
 
// используется исключительно для иллюстрации того, 
// как механизм технически мог бы разрулить проблему перегруженных функций
// автоматически выбрав ту версию, что подходит под нужный тип функции
template<class F> 
    std::function<F> 
        make( typename std::add_pointer<F>::type f)
    {
        return std::function<F>(f);
    }
 
 
//------------------------------------------------------------------------------
 
int func(int v) { cout << dFUNCTION << ": arg = "<< v<<'\n'; return 0; }
int func()      { cout << dFUNCTION << '\n'; return 0; }
 
 
int func(const std::function<int()>& callback)
{ 
    cout << dFUNCTION << '\n'; 
    if(callback)
        return callback();
    return 0;
}
 
template<class F> 
    decltype( std::function<F>()()  ) //<--- использование техники "Макет". 
    //Реального запуска фиктивного std::function не происходит
    //однако этого достаточно, что бы понять каким будет возвращаемый тип 
 
        // указанный в шаблонее тип преобразуется к указательному
        // получаем четкую сигнатуру
        // благодаря которой разрешаются перегрузки финкций    
        func( typename std::add_pointer<F>::type f)
        {
            //здесь уже создаем злополучный std::function
            //раз уж он самостоятельно не умеет разрешать перегрузки
    
            //возвращаемый тип мы уже вывели, 
            //так что теперь можно просто запустить его на выполнение
            return std::function<F>(f)();
        }
 
    
int main()
{
    std::cout << "Hello, world!\n";
    
    std::function<int()> f = static_cast<int(*)()>(&func);
    
    cout<<"---------------\n";
    func();
 
    cout<<"---------------\n";
    func(10);
 
    cout<<"---------------\n";
    func(f);
    
    cout<<"---------------\n";
    
    
    // использование функции с автоматическим разрешением перегруженныйх функци
    // странно, что std::function не использует внутри себя такую же технику
    const auto  stdfunction = make<int()>(&func);
    
    stdfunction();
    
    
    cout<<"---------------\n";
    // иллюстрация использования для перегруженной func
    func<int()>(&func);
        
    
}
Добавлено через 25 минут
можно ещё вот так:

http://rextester.com/GKLS32839

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
#include <iostream>
#include <functional>
#include <type_traits>
using namespace std;
 
//------------------------------------------------------------------------------
 
 
int func() { cout<<"int func()\n"; return 0; }
 
 
template<class F> 
    
    typename std::result_of< 
        typename std::add_pointer<F>::type ()
    >::type
 
    func( typename std::add_pointer<F>::type f)
    {
        return std::function<F>(f)();
    }
 
//------------------------------------------------------------------------------
    
int main()
{
    std::cout << "Hello, world!\n";
    
    cout<<"---------------\n";
    func<int()>(&func);
    
}
Хотя синтаксис определения типа возвращаемого значения конечно доставляет

Добавлено через 10 минут
Можно ещё вот так:

http://rextester.com/SFGI99421

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
#include <iostream>
#include <functional>
#include <type_traits>
using namespace std;
 
//------------------------------------------------------------------------------
 
 
int func() { cout<<"int func()\n"; return 0; }
 
 
template<class F, F* f> 
    typename std::result_of<F*()>::type
        func(){ return std::function<F>(f)(); }
 
//------------------------------------------------------------------------------
    
int main()
{
    std::cout << "Hello, world!\n";
    
    cout<<"---------------\n";
    
    func<int(), &func>();
}
Обратите внимание: здесь информация о функции передается через шапку шаблона.
Что в общем случае работает быстрее, чем передача данных через аргументы функции.
0
30 / 47 / 19
Регистрация: 23.10.2014
Сообщений: 1,001
05.01.2015, 20:47  [ТС] 7
hoggy, первый вариант это опять лишний код при вызове, варианты с шаблонами не годятся, потому что нужна жесткая типизация

Добавлено через 48 секунд
а собственно для разнообразия покажите кто нибудь пожалуйста как самым старым способом через указатели передавать, может так будет меньше кода хотя бы...

Добавлено через 12 минут
кстати имена вызываемой и передаваемой функций отличаются если что (вдруг важно)
0
Эксперт С++
8719 / 4262 / 950
Регистрация: 15.11.2014
Сообщений: 9,668
05.01.2015, 20:52 8
Лучший ответ Сообщение было отмечено Dark Byte как решение

Решение

Цитата Сообщение от Dark Byte Посмотреть сообщение
первый вариант это опять лишний код при вызове
Не уловил. О каком "лишнем коде" идет речь?

При работе с перегруженными функциями у вас есть только два варианта:

1. Вы сами вручную выполняете приведение типов

C++
1
func(  static_cast<int(*)()>(&foo) ); //foo - перегруженная фукция
2. Либо за вас это сделает умный шаблон:

C++
1
2
template<class F> return_type
  func( typename std::add_pointer<F>::type f){ ... }
Других способов работы с перегруженными функциями не существует.
Потому что компилятор - не телепат, и если ему явно не указать сигнатуру функции, то он не сможет догадаться, какая из перегрузок имеется ввиду.

Цитата Сообщение от Dark Byte Посмотреть сообщение
потому что нужна жесткая типизация

Шаблоно-код - это и есть "жесткая типизация".
Жестче некуда - все в статике. Все ошибки диагностируются времени компиляции.

Цитата Сообщение от Dark Byte Посмотреть сообщение
а собственно для разнообразия покажите кто нибудь пожалуйста как самым старым способом через указатели передавать, может так будет меньше кода хотя бы...

http://rextester.com/VMFAE32750


C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <iostream>
using namespace std;
 
int func(int) { return cout<<"int func(int)\n", 0; }
int func()    { return cout<<"int func()\n",    0; }
 
int f( int(*foo)() ) 
{
    return foo();
}
          
 
int main()
{
    std::cout << "Hello, world!\n";
    
    // можно так
    f( &func );
    
    // для "свободных" функций взятие адреса не обязательно
    f( func );
}
1
30 / 47 / 19
Регистрация: 23.10.2014
Сообщений: 1,001
05.01.2015, 21:19  [ТС] 9
Цитата Сообщение от hoggy Посмотреть сообщение
Не уловил. О каком "лишнем коде" идет речь?
Цитата Сообщение от hoggy Посмотреть сообщение
std::function<int()> f = static_cast<int(*)()>(&func);
Цитата Сообщение от hoggy Посмотреть сообщение
Вы сами вручную выполняете приведение типов
ну можно и так...
Цитата Сообщение от hoggy Посмотреть сообщение
Шаблоно-код - это и есть "жесткая типизация".
Жестче некуда - все в статике. Все ошибки диагностируются времени компиляции.
я имею ввиду что мне надо чтобы прототип функции всегда был один и тот же (допустим int()), а через шаблоны можно передать фактически любую функцию с любым типом...

а вот с указателями и правда меньше кода, но пока что не работает

Цитата Сообщение от hoggy Посмотреть сообщение
можно так
error C2102: для "&" требуется левостороннее значение
Цитата Сообщение от hoggy Посмотреть сообщение
для "свободных" функций взятие адреса не обязательно
error C2664: "int f(int (__cdecl *)(void))": невозможно преобразовать аргумент 1 из "int" в "int (__cdecl *)(void)"

Добавлено через 3 минуты
ааа все работает, скобки при вызове не надо было писать, спасибо за помощь
0
Эксперт С++
8719 / 4262 / 950
Регистрация: 15.11.2014
Сообщений: 9,668
05.01.2015, 21:34 10
Цитата Сообщение от Dark Byte Посмотреть сообщение
я имею ввиду что мне надо чтобы прототип функции всегда был один и тот же (допустим int()), а через шаблоны можно передать фактически любую функцию с любым типом...
Ну дык... если вам заранее известна сигнатура функции, с которой нужно работать, то и нет никакого смысла заморачиваться:

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
#include <iostream>
using namespace std;
 
int func(int) { return cout<<"int func(int)\n", 0; }
int func()    { return cout<<"int func()\n",    0; }
 
 
// я использую typedef что бы повысить читабельность
typedef int(*pFunction)();
 
 
// согласитесь, запись аргумента значительно упростилась
int f( pFunction foo ) 
{
    return foo();
}
          
 
int main()
{
    std::cout << "Hello, world!\n";
    
    // можно так
    f( &func );
    
    // для "свободных" функций взятие адреса не обязательно
    f( func );
}
Говорят, что с++ - путь тайпдефа.
Используйте тайпдефы над такими сложно-читабельными типами,
как указатель-на-функцию, что бы упростить синтаксис, и улучшить читабельность.

Не используйте std::function без необходимости.
Не используйте шаблоны без необходимости.
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
05.01.2015, 21:34
Помогаю со студенческими работами здесь

Как подменить константу переменной-параметром функции?
Всем здравствуйте. Есть функция в теле которой используется следующая конструкция: static short...

Не правильная работа memcpy с вектором - параметром функции
Есть функция int InitX( CUSTOMVERTEX InVertexes, int VertexCount ) { //... void*...

А какая разница между константным параметром и неконстантным в функции
Здравствуйте! 1. Если использовать просто неконстантный параметр string, то ничего не изменится и...

Передача функций в функции, замена инициализации функции ключевыми словами
Хочу сделать фишку по типу property в c++/cli int property a{ int get(){ return value; } }...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
10
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2022, CyberForum.ru