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

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

31.07.2023, 05:50. Показов 1984. Ответов 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
5164 / 3519 / 536
Регистрация: 01.06.2013
Сообщений: 7,653
Записей в блоге: 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
 Аватар для SmallEvil
4086 / 2975 / 813
Регистрация: 29.06.2020
Сообщений: 11,000
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
5164 / 3519 / 536
Регистрация: 01.06.2013
Сообщений: 7,653
Записей в блоге: 9
01.08.2023, 13:03  [ТС]
Цитата Сообщение от SmallEvil Посмотреть сообщение
Извините, если до меня до сих пор не дошла проблема из шапки.
Имеется dll и описание функций которые она экспортирует в виде документации. Значение констант которые указываются в значениях по умолчанию тоже приведены в документации. Больше ничего нет.
Дальше цитирую себя
Цитата Сообщение от Curry Посмотреть сообщение
В документации на dll-ку много функций и у них много аргументов со значениями по умолчанию. И вызываться эти функции будут из многих мест, и большинство аргументов по дефолту.
Подробнее уж не знаю как написать.
Сперва я, из описания функций в документации, понаделал типов-указателей через typedef-ы и обнаружил что плюсы не понимают в них дефолтных значений параметров, отсюда и возникла эта тема.

Добавлено через 4 минуты
SmallEvil, вариант с std::bind в принципе возможен, но не вижу чем он лучше моей обёртки.
Цитата Сообщение от SmallEvil Посмотреть сообщение
То есть в dll нельзя написать функцию с параметрами по умолчанию ?
В заголовочном файле то можно, но экспотируется она без них. Если нет библиотеки импорта, то приходится динамически загружать библиотеку (или я не знаю другие варианты).
При динамической загрузки из описания функций делаем типы-указатели на функции, в них, оказывается нельзя указывать параметры по умолчанию.
0
 Аватар для SmallEvil
4086 / 2975 / 813
Регистрация: 29.06.2020
Сообщений: 11,000
01.08.2023, 14:07
Добавлено через 11 минут
upd:
Цитата Сообщение от Curry Посмотреть сообщение
SmallEvil, вариант с std::bind в принципе возможен, но не вижу чем он лучше моей обёртки.
Из коробки. Меньше кода. Лучшая встраиваемость.
0
Модератор
 Аватар для Curry
5164 / 3519 / 536
Регистрация: 01.06.2013
Сообщений: 7,653
Записей в блоге: 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
 Аватар для SmallEvil
4086 / 2975 / 813
Регистрация: 29.06.2020
Сообщений: 11,000
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
5164 / 3519 / 536
Регистрация: 01.06.2013
Сообщений: 7,653
Записей в блоге: 9
01.08.2023, 14:32  [ТС]
Цитата Сообщение от SmallEvil Посмотреть сообщение
либо использовать по месту.
А чем это лучше простого вызова функции через указатель с явным заданием всех аргументов?
0
фрилансер
 Аватар для Алексей1153
6495 / 5726 / 1133
Регистрация: 11.10.2019
Сообщений: 15,286
01.08.2023, 14:34
SmallEvil, зачем мучаться с нечитабельным std::bind, если есть лямбда?
1
 Аватар для SmallEvil
4086 / 2975 / 813
Регистрация: 29.06.2020
Сообщений: 11,000
01.08.2023, 14:59
Цитата Сообщение от Алексей1153 Посмотреть сообщение
зачем мучаться с нечитабельным std::bind, если есть лямбда?
Да. Всему свое место и время. )
Не нужно себя мучать.

Действительно мало работал с dll, тем более чужими с неполным комплектом.
Вроде zayats80888, навел на то что нужно для такого поведения без нового уровня абстракции.
Осталось лишь найти необходимые инструменты.
1
19501 / 10106 / 2461
Регистрация: 30.01.2014
Сообщений: 17,825
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
Ответ Создать тему
Новые блоги и статьи
сукцессия 22. От артефактов к физиологии: калибровка агентной модели грибной сукцессии для воспроизведения сезонной динамики и pH-плато
anaschu 11.07.2026
Аннотация В данной работе представлена калибровка агентной модели динамики грибных сообществ (fungal-succession), направленная на устранение нефизичных артефактов (коллапс биомассы, мгновенное. . .
Сукцессия 20. Война автоботов. Делаем ставки. Лёд против "пш-пш!".
anaschu 11.07.2026
Битва ИИ в ризосфере: Как мы скрестили жесткие ОДУ, закон Фика и «подземный шантаж» Уважаемые коллеги! Хочу поделиться уникальным опытом ведения междисциплинарной компьютерной разработки. Прямо. . .
Сукцессия 19. Какие выводы я сделал из модели? Часть 2.Внутримикоризный стехиометрический буфер и хроно-дискретные зоны экспансии
anaschu 11.07.2026
Био-Инженерный Ликбез: Архитектура Модели Ризосферы Математический аппарат моделирования
Сукцессия 18. Какие выводы я сделал из войны грибов с деревьями? Часть 1- рассказ и немного про термины
anaschu 11.07.2026
Био-Инженерный Ликбез: Архитектура Модели Ризосферы Математический аппарат моделирования Система ОДУ описывает динамику изменения массы различных компонентов системы во времени. Ключевой. . .
Просветление в 5 секунд
kumehtar 10.07.2026
Андрей Веретенников выдал фразу недавно: "Вам не обязательно кем-то себя считать"
Эксперимент с картинкой-обложкой на CodinGame
Adler 10.07.2026
Решил на днях провести эксперимент. У меня есть аккаунт на CodinGame, ТОП-3 по РФ среди 2200 участников (в разделе соревнования по программированию ИИ-ботов). Там есть обложка, куда можно влепить. . .
GitDOS: Когда я решил скрестить MS-DOS, GitHub и Claude
MaGz GoLd 08.07.2026
Привет, Киберфорум! Хочу поделиться своим проектом, который, надеюсь, вас заинтересует. GitDOS — это веб-приложение, которое позволяет запускать DOS в браузере с тремя крутыми фичами: диски живут в. . .
Учебный мини "цифровой двойник" = (Сервер = Java + Flask_питон )+(3D = Гугловскаая 4T nvideo + google colab) +( WMS = Odoo на Docker)
anaschu 07.07.2026
Увидел в требованиях к вакансии создателя имитационных моделей связку (REst + Api + WMS + Anylogic + питон + 3D Nvideo), и решил посмотреть, что это такое. Из этого всего я работал более менее. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru