Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 5.00/8: Рейтинг темы: голосов - 8, средняя оценка - 5.00
Модератор
 Аватар для Curry
5153 / 3450 / 536
Регистрация: 01.06.2013
Сообщений: 7,517
Записей в блоге: 9

Параметры со значениями по умолчанию в описании типа указателя на функцию

31.07.2023, 05:50. Показов 1795. Ответов 31
Метки нет (Все метки)

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

Хочу что бы было возможно такое
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
#include <iostream>
 
typedef void (*funptr)(int i=28);
 
void foo(int i)
{
    std::cout << "Coo-coo from foo, i=" << i << std::endl;
}
 
int main(){
    funptr fp=foo;
    fp();
}
но оно невозможно.

А может как то и возможно?

p.s. Понятно что можно сделать функцию - обёртку со значениями по умолчанию, а внутри неё вызывать функцию по указателю, но громоздко.

Столкнулся с необходимость динамически загружать dll к которой есть только документация с сигнатурами экспортированных функций, и там полно параметров по умолчанию. Адреса функций добываю через GetProcAddress, но при конвертации сигнатур функций в указатели дефолтные значения приходится удалять. Непонятно, зачем в языке такое ограничение.
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
31.07.2023, 05:50
Ответы с готовыми решениями:

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

Как создать функцию, принимающую в качестве аргумента иную функцию, в которой есть параметры по умолчанию?
У меня имеется функция msk с параметрами по умолчанию double msk(double a = 0.0, double b = 1.0) И имеется функция test, в которую мне...

Сохранение параметра по-умолчанию при написания указателя на функцию
Допустим у меня есть класс с функцией и указателем на функцию class Bot { public: void Show(int a = -5); void...

31
Модератор
 Аватар для Curry
5153 / 3450 / 536
Регистрация: 01.06.2013
Сообщений: 7,517
Записей в блоге: 9
01.08.2023, 12:35  [ТС]
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от zayats80888 Посмотреть сообщение
заголовок + библиотека импорта (раз речь про dll)
Библиотеки импорта нет.
0
 Аватар для zayats80888
6352 / 3523 / 1428
Регистрация: 07.02.2019
Сообщений: 8,995
01.08.2023, 12:37
Цитата Сообщение от Curry Посмотреть сообщение
Библиотеки импорта нет.
Вроде, есть утилиты, которые умеют их делать...
1
Заблокирован
01.08.2023, 12:51
Цитата Сообщение от KSergey9 Посмотреть сообщение
Это как? статической линковкойс dll?
Парсинг мануала.

Curry, давайте на минуточку отложим аргументы по умолчанию самого языка С++.
Curry, я до конца не понял что именно вы хотите, как использовать аргументы по умолчанию.
Как гибко и фривольно вам это необходимо.
В с++ для работы с функциональными объектами и функциями есть модуль <functional>

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <iostream>
#include <functional>
using namespace std;
 
void foo(int, int, int, int, int);
void foo(int a1, int a2, int a3, int a4, int a5){
    std::cout << a1 << ' ' << a2 << ' ' << a3 << ' ' << a4 << ' ' << a5 << ' ' << std::endl;
};
 
using pf = void(*)(int, int, int, int, int);
 
int main()
{
    using namespace std::placeholders;  // for _1, _2, _3...
    
    pf f1 = foo;
    // templ1 - задаем параметры по умолчанию для 2-го, 4-го и 5-го аргументов 
    auto templ1 = std::bind(f1, _1, 2, _2, 4, 5);
    int a1=100, a3=300;
    templ1(a1,a3);
}
Code
1
100 2 300 4 5
Таких templ1 "шаблонов" вызова функций, можно создать столько, сколько необходимо.
Извините, если до меня до сих пор не дошла проблема из шапки.

Добавлено через 8 минут
Я мало работал с dll.
То есть в dll нельзя написать функцию с параметрами по умолчанию ?

Добавлено через 1 минуту
Ммм, да, кажется эти параметры по умолчанию, используются на уровне компиляции.
Верно ?
1
Модератор
 Аватар для Curry
5153 / 3450 / 536
Регистрация: 01.06.2013
Сообщений: 7,517
Записей в блоге: 9
01.08.2023, 13:03  [ТС]
Цитата Сообщение от SmallEvil Посмотреть сообщение
Извините, если до меня до сих пор не дошла проблема из шапки.
Имеется dll и описание функций которые она экспортирует в виде документации. Значение констант которые указываются в значениях по умолчанию тоже приведены в документации. Больше ничего нет.
Дальше цитирую себя
Цитата Сообщение от Curry Посмотреть сообщение
В документации на dll-ку много функций и у них много аргументов со значениями по умолчанию. И вызываться эти функции будут из многих мест, и большинство аргументов по дефолту.
Подробнее уж не знаю как написать.
Сперва я, из описания функций в документации, понаделал типов-указателей через typedef-ы и обнаружил что плюсы не понимают в них дефолтных значений параметров, отсюда и возникла эта тема.

Добавлено через 4 минуты
SmallEvil, вариант с std::bind в принципе возможен, но не вижу чем он лучше моей обёртки.
Цитата Сообщение от SmallEvil Посмотреть сообщение
То есть в dll нельзя написать функцию с параметрами по умолчанию ?
В заголовочном файле то можно, но экспотируется она без них. Если нет библиотеки импорта, то приходится динамически загружать библиотеку (или я не знаю другие варианты).
При динамической загрузки из описания функций делаем типы-указатели на функции, в них, оказывается нельзя указывать параметры по умолчанию.
0
Заблокирован
01.08.2023, 14:07
Добавлено через 11 минут
upd:
Цитата Сообщение от Curry Посмотреть сообщение
SmallEvil, вариант с std::bind в принципе возможен, но не вижу чем он лучше моей обёртки.
Из коробки. Меньше кода. Лучшая встраиваемость.
0
Модератор
 Аватар для Curry
5153 / 3450 / 536
Регистрация: 01.06.2013
Сообщений: 7,517
Записей в блоге: 9
01.08.2023, 14:12  [ТС]
Цитата Сообщение от SmallEvil Посмотреть сообщение
Меньше кода. Лучшая встраиваемость.
В одних случаях функцию понадобится вызывать со всему опциональными параметрами по умолчанию, в других часть или все параметры задавать явно. А std::bind спрячет их все. Ну, или делать на одну импортируемую функцию несколько биндов что вообще уже мрак.
0
631 / 526 / 104
Регистрация: 05.08.2022
Сообщений: 2,810
01.08.2023, 14:22
Цитата Сообщение от Curry Посмотреть сообщение
Библиотеки импорта нет.
Загуглить "как сделать lib из dll". Будет готовая инструкция.
Там просто, инструментарий есть в составе компилятора (во всяком случае в VS есть)
0
Заблокирован
01.08.2023, 14:23
Цитата Сообщение от Curry Посмотреть сообщение
А std::bind спрячет их все. Ну, или делать на одну импортируемую функцию несколько биндов что вообще уже мрак.
Либо мрак, либо использовать по месту.
C++
1
2
std::bind(f1, _1, 2, _2, 4, 5)(a1,a3);
std::bind(f1, _1, 2, 3, 4, 5)(a1);
0
Модератор
 Аватар для Curry
5153 / 3450 / 536
Регистрация: 01.06.2013
Сообщений: 7,517
Записей в блоге: 9
01.08.2023, 14:32  [ТС]
Цитата Сообщение от SmallEvil Посмотреть сообщение
либо использовать по месту.
А чем это лучше простого вызова функции через указатель с явным заданием всех аргументов?
0
фрилансер
 Аватар для Алексей1153
6444 / 5637 / 1128
Регистрация: 11.10.2019
Сообщений: 14,994
01.08.2023, 14:34
SmallEvil, зачем мучаться с нечитабельным std::bind, если есть лямбда?
1
Заблокирован
01.08.2023, 14:59
Цитата Сообщение от Алексей1153 Посмотреть сообщение
зачем мучаться с нечитабельным std::bind, если есть лямбда?
Да. Всему свое место и время. )
Не нужно себя мучать.

Действительно мало работал с dll, тем более чужими с неполным комплектом.
Вроде zayats80888, навел на то что нужно для такого поведения без нового уровня абстракции.
Осталось лишь найти необходимые инструменты.
1
19491 / 10097 / 2460
Регистрация: 30.01.2014
Сообщений: 17,805
02.08.2023, 14:03
Curry, код - идея. На "подумать", на "допилить". (С++20)
Кликните здесь для просмотра всего текста
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
#include <iostream>
#include <tuple>
#include <utility>
 
template <typename FType, typename Caller>
struct DefaultCaller;
 
template <typename R, typename ...Args, typename Caller>
struct DefaultCaller<R(Args...), Caller> : Caller
{
    using ThisType = DefaultCaller;
    using FunctionType = R(Args...);
    using ReturnType = R;
 
    DefaultCaller(FunctionType pFunc = nullptr)
        : m_pFunc(pFunc)
    { }
 
    template <typename ...LArgs>
    std::enable_if_t<
        (sizeof...(LArgs) <= sizeof...(Args))
      , ReturnType
    > operator()(LArgs&&... args) const
    {
        return Caller::operator()(
            [this](LArgs&&... args, auto&&... defArgs)
            {
                constexpr size_t cntDefArgsNeeded = sizeof...(Args) - sizeof...(LArgs);
                static_assert(cntDefArgsNeeded <= sizeof...(defArgs), "Invalid number of arguments!");
                
                constexpr size_t defArgIdx = sizeof...(defArgs) - cntDefArgsNeeded;
                return call<defArgIdx>(
                    std::forward_as_tuple(defArgs...)
                  , std::make_index_sequence<cntDefArgsNeeded>{}
                  , std::forward<LArgs>(args)...
                );
            }
          , std::forward<LArgs>(args)...
        );
    }
private:
    template <size_t Idx, typename Tuple, typename ...LArgs, size_t ...Is>
    std::enable_if_t<
        (sizeof...(LArgs) + sizeof...(Is)) == sizeof...(Args)
      , ReturnType
    > call(Tuple const& defArgs, std::index_sequence<Is...>, LArgs&&... args) const
    {
        return m_pFunc(std::forward<LArgs>(args)..., std::get<Idx + Is>(defArgs)...);
    }
 
private:
    FunctionType* m_pFunc;
};
 
#define FUNC_TYPEDEF(FType, ...) \
    typedef DefaultCaller< \
        FType, decltype([](auto back, auto&&... args){ \
                  return back(std::forward<decltype(args)>(args)... __VA_OPT__(,) __VA_ARGS__); \
               }) \
    >
 
 
 
void foo(int a, int b, double c) 
{
    std::cout << a << ' ' << b << ' ' << c << '\n';
}
int main() 
{
    FUNC_TYPEDEF(void(int, int, double), 1, 42, 3.14) FPtr1;
    FUNC_TYPEDEF(void(int, int, double), 42, 3.14) FPtr2;
    
    FPtr1 p1 = &foo;
    FPtr2 p2;
    p2 = &foo;
 
    p1();   // pass 1, 42, 3.14
    p1(11); // pass 11, 42, 3.14
    p1(11, 22); // pass 11, 22, 3.14
    p1(11, 22, 3.3); // pass 11, 22, 3,3
 
    // p2() error
    p2(11);
    p2(11, 22);
    p2(11, 22, 3.3);
    //p2(11, 22, 33, 44) error
}

https://wandbox.org/permlink/09gTnY8dRF5dr1aM

Можно спустить требование до с++14, но тогда такой typedef нельзя будет сделать локально в функции (но код упростится).

Добавлено через 15 минут
У MSVC какая-то проблема с __VA_OPT__, поэтому так:
Кликните здесь для просмотра всего текста
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
#include <iostream>
#include <tuple>
#include <utility>
 
template <typename FType, typename Caller>
struct DefaultCaller;
 
template <typename R, typename ...Args, typename Caller>
struct DefaultCaller<R(Args...), Caller> : Caller
{
    using ThisType = DefaultCaller;
    using FunctionType = R(Args...);
    using ReturnType = R;
 
    DefaultCaller(FunctionType pFunc = nullptr)
        : m_pFunc(pFunc)
    { }
 
    template <typename ...LArgs>
    std::enable_if_t<
        (sizeof...(LArgs) <= sizeof...(Args))
      , ReturnType
    > operator()(LArgs&&... args) const
    {
        return Caller::operator()(
            [this](LArgs&&... args, auto const& defArgs)
            {
                constexpr size_t cntDefArgs = std::tuple_size_v<
                    std::remove_reference_t<decltype(defArgs)>
                >;
                constexpr size_t cntDefArgsNeeded = sizeof...(Args) - sizeof...(LArgs);
                static_assert(cntDefArgsNeeded <= cntDefArgs, "Invalid number of arguments!");
                
                constexpr size_t defArgIdx = cntDefArgs - cntDefArgsNeeded;
                return call<defArgIdx>(
                    defArgs
                  , std::make_index_sequence<cntDefArgsNeeded>{}
                  , std::forward<LArgs>(args)...
                );
            }
          , std::forward<LArgs>(args)...
        );
    }
private:
    template <size_t Idx, typename Tuple, typename ...LArgs, size_t ...Is>
    std::enable_if_t<
        (sizeof...(LArgs) + sizeof...(Is)) == sizeof...(Args)
      , ReturnType
    > call(Tuple const& defArgs, std::index_sequence<Is...>, LArgs&&... args) const
    {
        return m_pFunc(std::forward<LArgs>(args)..., std::get<Idx + Is>(defArgs)...);
    }
 
private:
    FunctionType* m_pFunc;
};
 
#define FUNC_TYPEDEF(FType, ...) \
    typedef DefaultCaller< \
        FType, decltype([](auto back, auto&&... args){ \
                  return back(std::forward<decltype(args)>(args)..., std::make_tuple(__VA_ARGS__)); \
               }) \
    >
 
 
 
void foo(int a, int b, double c) 
{
    std::cout << a << ' ' << b << ' ' << c << '\n';
}
int main() 
{
    FUNC_TYPEDEF(void(int, int, double), 1, 42, 3.14) FPtr1;
    FUNC_TYPEDEF(void(int, int, double), 42, 3.14) FPtr2;
    
    FPtr1 p1 = &foo;
    FPtr2 p2;
    p2 = &foo;
 
    p1();   // pass 1, 42, 3.14
    p1(11); // pass 11, 42, 3.14
    p1(11, 22); // pass 11, 22, 3.14
    p1(11, 22, 3.3); // pass 11, 22, 3,3
 
    // p2() error
    p2(11);
    p2(11, 22);
    p2(11, 22, 3.3);
    //p2(11, 22, 33, 44) error
}

Ссылка: https://godbolt.org/z/5TTbKPYrc

Добавлено через 18 минут
Упрощаем (на основе предыдущего варианта)
Кликните здесь для просмотра всего текста
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
#include <iostream>
#include <tuple>
#include <utility>
 
template <typename FType, typename Caller>
struct DefaultCaller;
 
template <typename R, typename ...Args, typename Caller>
struct DefaultCaller<R(Args...), Caller> : Caller
{
    using ThisType = DefaultCaller;
    using FunctionType = R(Args...);
    using ReturnType = R;
 
    DefaultCaller(FunctionType pFunc = nullptr)
        : m_pFunc(pFunc)
    { }
 
    template <typename ...LArgs>
    std::enable_if_t<
        (sizeof...(LArgs) <= sizeof...(Args))
      , ReturnType
    > operator()(LArgs&&... args) const
    {
        auto const& defArgs = Caller::operator()();
        constexpr size_t cntDefArgs = std::tuple_size_v<
            std::remove_reference_t<decltype(defArgs)>
        >;
        constexpr size_t cntDefArgsNeeded = sizeof...(Args) - sizeof...(LArgs);
        static_assert(cntDefArgsNeeded <= cntDefArgs, "Invalid number of arguments!");
                
        constexpr size_t defArgIdx = cntDefArgs - cntDefArgsNeeded;
        return call<defArgIdx>(
               defArgs
             , std::make_index_sequence<cntDefArgsNeeded>{}
             , std::forward<LArgs>(args)...
        );
    }
private:
    template <size_t Idx, typename Tuple, typename ...LArgs, size_t ...Is>
    std::enable_if_t<
        (sizeof...(LArgs) + sizeof...(Is)) == sizeof...(Args)
      , ReturnType
    > call(Tuple const& defArgs, std::index_sequence<Is...>, LArgs&&... args) const
    {
        return m_pFunc(std::forward<LArgs>(args)..., std::get<Idx + Is>(defArgs)...);
    }
 
private:
    FunctionType* m_pFunc;
};
 
#define FUNC_TYPEDEF(FType, ...) \
    typedef DefaultCaller<FType, decltype([](){ return std::make_tuple(__VA_ARGS__); })>
 
 
 
void foo(int a, int b, double c) 
{
    std::cout << a << ' ' << b << ' ' << c << '\n';
}
int main() 
{
    FUNC_TYPEDEF(void(int, int, double), 1, 42, 3.14) FPtr1;
    FUNC_TYPEDEF(void(int, int, double), 42, 3.14) FPtr2;
    FUNC_TYPEDEF(void(int, int, double)) FPtr3;
    
    FPtr1 p1 = &foo;
    FPtr2 p2;
    p2 = &foo;
    FPtr3 p3 = &foo;
 
    p1();   // pass 1, 42, 3.14
    p1(11); // pass 11, 42, 3.14
    p1(11, 22); // pass 11, 22, 3.14
    p1(11, 22, 3.3); // pass 11, 22, 3,3
 
    // p2() error
    p2(11);
    p2(11, 22);
    p2(11, 22, 3.3);
    //p2(11, 22, 33, 44) error
 
    p3(1, 2, 3);
}
2
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
02.08.2023, 14:03
Помогаю со студенческими работами здесь

Указатель на функцию и параметры по умолчанию
Приветствую! Есть такая задача - мне нужно передавать в специальную функцию массив и указатель на функцию. Функции эти для сортировки, и...

Реализовать функцию max, использующую параметры по умолчанию
1. Реализовать функцию, использующую параметры по умолчанию. Функция max(xi×x j),i∈, j∈,i≠ j Тип параметров double ...

Передача типа указателя на функцию
Всем привет. Недавно в теме начинающих возник вопрос, а можно ли передать тип (указатель на функцию) без использования typedef: ...

Преобразование типа для указателя на функцию
Есть враппер SQLite, которым успешно пользуюсь в CBuilder и MVC. Возникла необходимость портирования в GCC - и случилась неудачка. ...

Как правильно пользоваться typedef для декларации типа указателя на функцию?
Мне нужны будут функции, принимающие параметр-указатель на функции с одним и тем же списком параметров и возвращаемым типом. Как правильно...


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

Или воспользуйтесь поиском по форуму:
32
Ответ Создать тему
Новые блоги и статьи
Thinkpad X220 Tablet — это лучший бюджетный ноутбук для учёбы, точка.
Programma_Boinc 23.12.2025
Thinkpad X220 Tablet — это лучший бюджетный ноутбук для учёбы, точка. Рецензия / Мнение Это мой обзор планшета X220 с точки зрения школьника. Недавно я решила попытаться уменьшить свой. . .
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Как объединить две одинаковые БД Access с разными данными
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru