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

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

05.01.2015, 17:29. Показов 2463. Ответов 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)
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
05.01.2015, 17:29
Ответы с готовыми решениями:

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

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

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

9
267 / 170 / 40
Регистрация: 25.08.2014
Сообщений: 1,087
Записей в блоге: 1
05.01.2015, 17:41
Передавай как указатель на функцию, явно приводи к указателю на нужный тип.
Вообще у тебя не объявлен тип-прототип для функции func.
0
30 / 47 / 19
Регистрация: 23.10.2014
Сообщений: 1,001
05.01.2015, 17:45  [ТС]
Цитата Сообщение от Enno Посмотреть сообщение
Передавай как указатель на функцию, явно приводи к указателю на нужный тип.
а чем std::function то не устраивает? чай не managed C, плюсы все же, значит надо пользоваться преимуществами... да и с указателями вызов затрудняется...
Цитата Сообщение от Enno Посмотреть сообщение
Вообще у тебя не объявлен тип-прототип для функции func.
как это не объявлен, а выше что?
0
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
05.01.2015, 17:53
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  [ТС]
Цитата Сообщение от hoggy Посмотреть сообщение
Callback f = static_cast<int(*)()>(&func);
вот в том то и дело хотелось бы обойтись без дополнительных объявлений если это возможно, просто подал название функции, ну может параметры функции или шаблона еще...
0
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
05.01.2015, 19:32
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  [ТС]
hoggy, первый вариант это опять лишний код при вызове, варианты с шаблонами не годятся, потому что нужна жесткая типизация

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

Добавлено через 12 минут
кстати имена вызываемой и передаваемой функций отличаются если что (вдруг важно)
0
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
05.01.2015, 20:52
Лучший ответ Сообщение было отмечено 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  [ТС]
Цитата Сообщение от 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
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
05.01.2015, 21:34
Цитата Сообщение от 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
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
05.01.2015, 21:34
Помогаю со студенческими работами здесь

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

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

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

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

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


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

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

Новые блоги и статьи
JWT аутентификация в ASP.NET Core
UnmanagedCoder 18.06.2025
Разрабатывая веб-приложения, я постоянно сталкиваюсь с дилеммой: как обеспечить надежную аутентификацию пользователей без ущерба для производительности и масштабируемости? Классические подходы на. . .
Краткий курс по С#
aaLeXAA 18.06.2025
Здесь вы найдете все необходимые функции чтоб написать програму на C# Задание 1: КЛАСС FORM 1 public partial class Form1 : Form { Spisok listin = new Spisok(); . . .
50 самых полезных примеров кода Python для частых задач
py-thonny 17.06.2025
Эффективность работы разработчика часто измеряется не количеством написаных строк, а скоростью решения задач. Готовые сниппеты значительно ускоряют разработку, помогают избежать типичных ошибок и. . .
C# и продвинутые приемы работы с БД
stackOverflow 17.06.2025
Каждый . NET разработчик рано или поздно сталкивается с ситуацией, когда привычные методы работы с базами данных превращаются в источник бессонных ночей. Я сам неоднократно попадал в такие ситуации,. . .
Angular: Вопросы и ответы на собеседовании
Reangularity 15.06.2025
Готовишься к техническому интервью по Angular? Я собрал самые распространенные вопросы, с которыми сталкиваются разработчики на собеседованиях в этом году. От базовых концепций до продвинутых. . .
Архитектура Onion в ASP.NET Core MVC
stackOverflow 15.06.2025
Что такое эта "луковая" архитектура? Термин предложил Джеффри Палермо (Jeffrey Palermo) в 2008 году, и с тех пор подход только набирал обороты. Суть проста - представьте себе лук с его. . .
Unity 4D
GameUnited 13.06.2025
Четырехмерное пространство. . . Звучит как что-то из научной фантастики, правда? Однако для меня, как разработчика со стажем в игровой индустрии, четвертое измерение давно перестало быть абстракцией из. . .
SSE (Server-Sent Events) в ASP.NET Core и .NET 10
UnmanagedCoder 13.06.2025
Кажется, Microsoft снова подкинула нам интересную фичу в новой версии фреймворка. Работая с превью . NET 10, я наткнулся на нативную поддержку Server-Sent Events (SSE) в ASP. NET Core Minimal APIs. Эта. . .
С днём независимости России!
Hrethgir 13.06.2025
Решил побеседовать, с утра праздничного дня, с LM о завоеваниях. То что она написала о народе, представителем которого я являюсь сам сначала возмутило меня, но дальше только смешило. Это чисто. . .
Лето вокруг.
kumehtar 13.06.2025
Лето вокруг. Наполненное бурями и ураганами событий. На фоне магии Жизни, священной и вечной, неумелой рукой человека рисуется панорама душевного непокоя. Странные серые краски проникают и. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru