Форум программистов, компьютерный форум, киберфорум
C++
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.84/49: Рейтинг темы: голосов - 49, средняя оценка - 4.84
:)
Эксперт С++
4773 / 3267 / 497
Регистрация: 19.02.2013
Сообщений: 9,046

Передача типа указателя на функцию

27.06.2013, 17:26. Показов 10561. Ответов 20
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Всем привет.

Недавно в теме начинающих возник вопрос, а можно ли передать тип (указатель на функцию) без использования typedef:
C++
1
2
typedef void (*func)(void);
func f = va_arg(vl,func);
Конкретно речь идет о втором аргументе макроса va_arg (из <cstdarg>).
Первое, что пришло на ум, это использование decltype. Но всё же эта фишка C++11. А есть ли решение в старом стиле?

Заранее спасибо.

Добавлено через 6 часов 36 минут
@vxg предложил такой вариант:
Кликните здесь для просмотра всего текста
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
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
 
int my_super_function(int x)
{
    return 2 * x;
}
 
void my_super_puper_function(const char *format, ...)
{
    va_list arglist;
    va_start(arglist, format);
    int (*f)(int x) = (int (*)(int x))va_arg(arglist, void *);
    printf("%i\n", f(2));
    va_end(arglist);
}
 
int main(int argc, char* argv[])
{
    my_super_puper_function("%p", my_super_function);
    system("pause");
    return 0;
}
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
27.06.2013, 17:26
Ответы с готовыми решениями:

Передача указателя на функцию-член
Всем привет ! Необходимо передать функцию-член в качестве параметра другой функции-члену. Следующий код class Menu { ...

Передача объекта типа TStringGrid в функцию в Embarcadero C++
Здравствуйте. Недавно начал изучать embarcadero c++ builder и столкнулся с проблемой: при передаче объекта типа TStringGrid в функцию...

Передача указателя на CALLBACK функцию
делаю класс приложения для более быстрого создания программ и просто инкапсуляции всего и вся)) и вот я сделал класс cApplication, один...

20
В астрале
Эксперт С++
 Аватар для ForEveR
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
28.06.2013, 10:06
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <boost/typeof/typeof.hpp>
#include <iostream>
 
#include <cstdarg>
 
int my_super_function(int x)
{
    return 2 * x;
}
 
void my_super_puper_function(const char *format, ...)
{
    va_list arglist;
    va_start(arglist, format);
    typeof(my_super_function)* f = (typeof(my_super_function)*)va_arg(arglist, void *);
    std::cout << f(2) << std::endl;
    va_end(arglist);
}
 
int main()
{
   my_super_puper_function("%p", my_super_function);
}
1
:)
Эксперт С++
4773 / 3267 / 497
Регистрация: 19.02.2013
Сообщений: 9,046
28.06.2013, 11:22  [ТС]
@ForEveR, только вот один момент. Я так понимаю, возможность преобразования указателя на функцию (или на функцию-член) в void* и обратно, зависит от реализации.
§ 5.2.10/8:
Converting a function pointer to an object pointer type or vice versa is conditionally-supported. The meaning of such a conversion is implementation-defined, except that if an implementation supports conversions in both directions, converting a prvalue of one type to the other type and back, possibly with different cvqualification, shall yield the original pointer value.
0
В астрале
Эксперт С++
 Аватар для ForEveR
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
28.06.2013, 11:31
@Tulosba, Вцелом, да.
C++
1
typeof(my_super_function)* f = va_arg(arglist, typeof(my_super_function)*);
Тогда так)
1
:)
Эксперт С++
4773 / 3267 / 497
Регистрация: 19.02.2013
Сообщений: 9,046
28.06.2013, 11:38  [ТС]
@ForEveR, а во что в итоге разворачивается boost typeof?
0
В астрале
Эксперт С++
 Аватар для ForEveR
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
28.06.2013, 11:49
@Tulosba, В зависимости от компилятора. Для GNU использует их typeof к примеру.
Я тут прогнал кстати. Там должно быть BOOST_TYPEOF, ибо typeof это я как раз использовал нативный.

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <boost/typeof/typeof.hpp>
#include <iostream>
 
#include <cstdarg>
 
int my_super_function(int x)
{
    return 2 * x;
}
 
void my_super_puper_function(const char *format, ...)
{
    va_list arglist;
    va_start(arglist, format);
    BOOST_TYPEOF(my_super_function)* f = va_arg(arglist, BOOST_TYPEOF(my_super_function)*);
    std::cout << f(2) << std::endl;
    va_end(arglist);
}
 
int main()
{
   my_super_puper_function("%p", my_super_function);
}
0
:)
Эксперт С++
4773 / 3267 / 497
Регистрация: 19.02.2013
Сообщений: 9,046
28.06.2013, 11:55  [ТС]
@ForEveR, что-то мне кажется, что с введением decltype смысла в гнушном typeof поубавится.
0
В астрале
Эксперт С++
 Аватар для ForEveR
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
28.06.2013, 11:59
@Tulosba, Поубавится конечно. Но мы же сейчас о С++03 говорит, а не С++11.
0
:)
Эксперт С++
4773 / 3267 / 497
Регистрация: 19.02.2013
Сообщений: 9,046
28.06.2013, 12:10  [ТС]
Цитата Сообщение от ForEveR Посмотреть сообщение
Но мы же сейчас о С++03 говорит, а не С++11.
да-да просто дискутирую

Добавлено через 7 минут
Но, вообще-то, я предполагал, что найдется какое-то решение передать тип вторым параметром va_arg, не прибегая к typedef, ну и дополнительно хотелось бы иметь переносимость. А теперь еще можно было бы добавить запрет на использование сторонних библиотек типа Boost. Короче говоря, чтоб голый C++03.
0
В астрале
Эксперт С++
 Аватар для ForEveR
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
28.06.2013, 12:40
@Tulosba, Тогда единственный норм вариант - это вариант vgx без использования void*.
C++
1
int (*f)(int x) = va_arg(arglist, int (*)(int));
0
:)
Эксперт С++
4773 / 3267 / 497
Регистрация: 19.02.2013
Сообщений: 9,046
28.06.2013, 12:55  [ТС]
C++
1
int (*f)(int x) = va_arg(arglist, int (*)(int));
Студия не жрет А ideone съел. У меня, собственно вопрос и возник из-за того, что студия не съела.
0
В астрале
Эксперт С++
 Аватар для ForEveR
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
28.06.2013, 13:03
@Tulosba, А что говорит-то?
0
:)
Эксперт С++
4773 / 3267 / 497
Регистрация: 19.02.2013
Сообщений: 9,046
28.06.2013, 13:39  [ТС]
Цитата Сообщение от ForEveR Посмотреть сообщение
А что говорит-то?
Вот:
Error 1 error C2059: syntax error : ')'
2 IntelliSense: expected an expression
Миниатюры
Передача типа указателя на функцию  
0
:)
Эксперт С++
4773 / 3267 / 497
Регистрация: 19.02.2013
Сообщений: 9,046
28.06.2013, 13:59  [ТС]
Видимо проблема в реализации макроса. В VS 2012 так:
C++
1
2
3
#define _crt_va_start(ap,v)  ( ap = (va_list)_ADDRESSOF(v) + _INTSIZEOF(v) )
#define _crt_va_arg(ap,t)    ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )
#define _crt_va_end(ap)      ( ap = (va_list)0 )
Надо посмотреть, что у GCC. Правда я уперся в
C++
1
__builtin_va_arg(__p1,__p2)
0
В астрале
Эксперт С++
 Аватар для ForEveR
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
28.06.2013, 15:16
@Tulosba, Ну... В gcc все серьезнее.)
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
    case RID_VA_ARG:
      {
        tree expression;
        tree type;
        source_location type_location;
 
        /* The `__builtin_va_arg' construct is used to handle
           `va_arg'.  Consume the `__builtin_va_arg' token.  */
        cp_lexer_consume_token (parser->lexer);
        /* Look for the opening `('.  */
        cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN);
        /* Now, parse the assignment-expression.  */
        expression = cp_parser_assignment_expression (parser,
                              /*cast_p=*/false, NULL);
        /* Look for the `,'.  */
        cp_parser_require (parser, CPP_COMMA, RT_COMMA);
        type_location = cp_lexer_peek_token (parser->lexer)->location;
        /* Parse the type-id.  */
        type = cp_parser_type_id (parser);
        /* Look for the closing `)'.  */
        cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
        /* Using `va_arg' in a constant-expression is not
           allowed.  */
        if (cp_parser_non_integral_constant_expression (parser,
                                NIC_VA_ARG))
          return error_mark_node;
        return build_x_va_arg (type_location, expression, type);
      }
Ну а дальше уже работа с деревом.
0
:)
Эксперт С++
4773 / 3267 / 497
Регистрация: 19.02.2013
Сообщений: 9,046
28.06.2013, 15:21  [ТС]

Не по теме:

Цитата Сообщение от ForEveR Посмотреть сообщение
Ну а дальше уже работа с деревом.
да тут не одно дерево, а целый темный лес :D


Интересно было бы MS-макрос полечить, чтоб он умел как gcc тип принимать.
0
В астрале
Эксперт С++
 Аватар для ForEveR
8049 / 4806 / 655
Регистрация: 24.06.2010
Сообщений: 10,562
28.06.2013, 20:14
Вцелом, т.к. в MSVC все ок с переводом из void* в function-pointer то почему бы не

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 <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
 
int my_super_function(int x)
{
    return 2 * x;
}
 
#ifdef _MSC_VER
#define VA_ARG_FUNCTION(arglist, signature) \
    (signature)va_arg((arglist), void*)
#else
#define VA_ARG_FUNCTION(arglist, signature) \
    va_arg((arglist), signature)
#endif
 
void my_super_puper_function(const char *format, ...)
{
    va_list arglist;
    va_start(arglist, format);
    int (*f)(int x) = VA_ARG_FUNCTION(arglist, int(*)(int));
    printf("%i\n", f(2));
    va_end(arglist);
}
 
int main(int argc, char* argv[])
{
    my_super_puper_function("%p", my_super_function);
    system("pause");
    return 0;
}
0
 Аватар для Kastaneda
5232 / 3205 / 362
Регистрация: 12.12.2009
Сообщений: 8,143
Записей в блоге: 2
30.06.2013, 17:06
Вот что придумал на базе кода из первого поста:
вводим дополнительную сущность
C++
1
2
3
4
union fptr
{
    int (*ptr)(int);
};
внтури my_super_puper_function()
C++
1
int (*f)(int x) = va_arg(arglist, fptr).ptr;
итого весь код
Кликните здесь для просмотра всего текста
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
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
 
int my_super_function(int x)
{
    return 2 * x;
}
 
union fptr
{
    int (*ptr)(int);
};
 
void my_super_puper_function(const char *format, ...)
{
    va_list arglist;
    va_start(arglist, format);
    int (*f)(int x) = va_arg(arglist, fptr).ptr;
    printf("%i\n", f(2));
    va_end(arglist);
}
 
int main(int argc, char* argv[])
{
    my_super_puper_function("%p", my_super_function);
    system("pause");
    return 0;
}
1
:)
Эксперт С++
4773 / 3267 / 497
Регистрация: 19.02.2013
Сообщений: 9,046
30.06.2013, 17:22  [ТС]
@Kastaneda, интересный подход. А union вместо struct потому что на 1 символ короче?
0
 Аватар для Kastaneda
5232 / 3205 / 362
Регистрация: 12.12.2009
Сообщений: 8,143
Записей в блоге: 2
30.06.2013, 17:28
Цитата Сообщение от Tulosba Посмотреть сообщение
А union вместо struct потому что на 1 символ короче?
Вообще можно было и struct, но union можно расширять
C++
1
2
3
4
5
union fptr
{
    int (*ptr1)(int);
    void (*ptr2)(int);
};
без увеличения занимаемого им места, а struct нет. Расширение может понадобиться для того, чтобы избежать привидение типа внутри my_super_puper_function(). Хотя преимущество конечно спорное, т.к. расширять можно до бесконечности и всех вариантов все равно не переберешь. Поэтому наверное практичней сделать ptr как void(*ptr)(), а внути my_super_puper_function() уже руками приводить к чему надо.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
30.06.2013, 17:28
Помогаю со студенческими работами здесь

Передача указателя на шаблонную функцию в другую функцию
Пишу тест для нескольких улучшений квиксорта с измерением времени. Функция benchmark принимает итераторы для диапазона элементов, указатель...

передача указателя на функцию
Помогите исправить ошибку уже незнаю как быть В бивает ту ошибку error C2664: Generate: невозможно преобразовать параметр 2 из...

Передача указателя на функцию
Доброго дня Форумчане. Хотелось бы узнать как вызывать функцию получив на нее указатель? пример class C1 { public: void...

Передача в функцию указателя
Почему плохо передавать в функцию указатель на строку или массив и возвращать указатель на строку или массив?

Передача указателя на функцию
Друзья подскажите пожалуйста где ошибка. Я хочу передать указатель на функцию из экземпляра класса cThreadPool в главный класс. Возникает...


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
SDL3 для Desktop (MinGW): Создаём пустое окно с нуля для 2D-графики на SDL3, Си и C++
8Observer8 10.03.2026
Содержание блога Финальные проекты на Си и на C++: hello-sdl3-c. zip hello-sdl3-cpp. zip Результат:
Установка CMake и MinGW 13.1 для сборки С и C++ приложений из консоли и из Qt Creator в EXE
8Observer8 10.03.2026
Содержание блога MinGW - это коллекция инструментов для сборки приложений в EXE. CMake - это система сборки приложений. Здесь описаны базовые шаги для старта программирования с помощью CMake и. . .
Как дизайн сайта влияет на конверсию: 7 решений, которые реально повышают заявки
Neotwalker 08.03.2026
Многие до сих пор воспринимают дизайн сайта как “красивую оболочку”. На практике всё иначе: дизайн напрямую влияет на то, оставит человек заявку или уйдёт через несколько секунд. Даже если у вас. . .
Модульная разработка через nuget packages
DevAlt 07.03.2026
Сложившийся в . Net-среде способ разработки чаще всего предполагает монорепозиторий в котором находятся все исходники. При создании нового решения, мы просто добавляем нужные проекты и имеем. . .
Модульный подход на примере F#
DevAlt 06.03.2026
В блоге дяди Боба наткнулся на такое определение: В этой книге («Подход, основанный на вариантах использования») Ивар утверждает, что архитектура программного обеспечения — это структуры,. . .
Управление камерой с помощью скрипта OrbitControls.js на Three.js: Вращение, зум и панорамирование
8Observer8 05.03.2026
Содержание блога Финальная демка в браузере работает на Desktop и мобильных браузерах. Итоговый код: orbit-controls-threejs-js. zip. Сканируйте QR-код на мобильном. Вращайте камеру одним пальцем,. . .
SDL3 для Web (WebAssembly): Синхронизация спрайтов SDL3 и тел Box2D
8Observer8 04.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-sync-physics-sprites-sdl3-c. zip На первой гифке отладочные линии отключены, а на второй включены:. . .
SDL3 для Web (WebAssembly): Идентификация объектов на Box2D v3 - использование userData и событий коллизий
8Observer8 02.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-collision-events-sdl3-c. zip Сканируйте QR-код на мобильном и вы увидите, что появится джойстик для управления главным героем. . . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru