Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 5.00/9: Рейтинг темы: голосов - 9, средняя оценка - 5.00
-1 / 25 / 4
Регистрация: 27.11.2017
Сообщений: 375

Можно ли в C++ определить функцию, которая возвращает указатель на функцию с той же сигнатурой?

13.01.2018, 17:21. Показов 2224. Ответов 20
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Вопрос такой, а можно ли в C++ определить функцию, которая возвращает указатель на эту же функцию, то есть на функцию с такой же самой сигнатурой?
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
13.01.2018, 17:21
Ответы с готовыми решениями:

Как сделать функцию, возвращающую указатель на функцию (которая в свою очередь возвращает указатель на массив)
Изучаю c++ по одной книжке.Она говорить не умеет.. Так вот понадобилось написать функцию,которая как параметр получает указатель на...

Написать функцию, которая возвращает указатель на первое вхождение подстроки string2 в строке string1
char* strstr(char* string1, char* string2) Возвращает указатель на первое вхождение подстроки string2 в строке string1. В случае неудачи...

Разработать и испытать функцию, которая переворачивает строку и возвращает указатель на перевёрнутую строку
Разработать и испытать функцию, которая переворачивает строку и возвращает указатель на перевёрнутую строку. Прототип функции инверсии...

20
зомбяк
 Аватар для TRam_
1585 / 1219 / 345
Регистрация: 14.05.2017
Сообщений: 3,940
13.01.2018, 18:26
А возвращать она что должна? Указатель на саму себя или nullptr ?
0
-1 / 25 / 4
Регистрация: 27.11.2017
Сообщений: 375
13.01.2018, 18:31  [ТС]
Это и есть суть вопроса, а точнее его часть.
А возвращать она должна указатель на функцию той же самой сигнатуры, что и она сама.
0
Эксперт С++
 Аватар для hoggy
8973 / 4319 / 960
Регистрация: 15.11.2014
Сообщений: 9,760
13.01.2018, 18:32
Цитата Сообщение от Просто Саша Посмотреть сообщение
Вопрос такой, а можно ли в C++ определить функцию, которая возвращает указатель на эту же функцию, то есть на функцию с такой же самой сигнатурой?
рекурсивный указатель на функцию:

http://rextester.com/WMXS26782

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
#include <iostream>
#include <functional>
 
class recursivePointer
{
    typedef std::function<void(const size_t)> 
        functor;
public:
    template<class T> recursivePointer(T&& v)
        :mCaller( std::bind(v, v, std::placeholders::_1) )
    {}
    
    recursivePointer(const functor& v)
        :mCaller(v)
    {}
    recursivePointer(functor&& v)
        :mCaller( std::move(v) )
    {}
    
    void operator()(const size_t depth)const 
        { mCaller(depth); }
    
    operator const functor&()const
        { return mCaller; }
    
private:    
    functor mCaller;
};
 
void foo(const recursivePointer& f, const size_t depth)
{
    if(depth == 0)
        return;
    
    std::cout<<"depth recursieve: "<< depth << '\n';
    f(depth - 1);
}
 
int main()
{
    std::cout << "Hello, world!\n";
    
    const auto pFunc = recursivePointer(&foo);
    
    foo(pFunc, 10);
    std::cout<< "--------------\n";
    
    foo(foo, 10);
    std::cout<< "--------------\n";
    
    foo(&foo, 10);
    std::cout<< "--------------\n";
}
2
зомбяк
 Аватар для TRam_
1585 / 1219 / 345
Регистрация: 14.05.2017
Сообщений: 3,940
13.01.2018, 19:33
hoggy, прикольно. Потому что для обычных указателей даже с конечной глубиной вызовов всё выглядело бы печально:

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
typedef int (*foo_type)();
typedef foo_type (*foo_type1)();
typedef foo_type1 (*foo_type2)();
 
int q()
{
    return 3;
}
 
foo_type foo()
{
    return &q;
}
 
foo_type1 foo1()
{
    return &foo;
}
 
foo_type2 foo2()
{
    return &foo1;
}
 
int main()
{ 
    int result = (* (* (* (*foo2)() )() )() )() ;
}
Добавлено через 5 минут
Другой вопрос - зачем это нужно, если переключать указатели на одном уровне вложенности не на что (т.к. указатель на свою собственную сигнатуру всего один). Ведь это полностью аналогично обычной рекурсии, реализуемой без всяких указателей

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

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
typedef void *foo_type();
 
foo_type *foo()
{
    return reinterpret_cast<foo_type *>( &foo );
}
 
int main()
{ 
    foo_type *p = foo();
 
    for(int i = 0; i < 10; i++)
        p = reinterpret_cast<foo_type *>((*p)());
}
Добавлено через 9 минут
Или так (то же самое, только звёздочки внутрь типа упрятаны):
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <iostream>
 
typedef void *(*foo_type)(int level);
 
foo_type foo(int level)
{
    std::cout << level << std::endl;
    return reinterpret_cast<foo_type>( &foo );
}
 
int main()
{ 
    foo_type p = foo(0);
 
    for(int i = 1; i < 10; i++)
        p = reinterpret_cast<foo_type>((*p)(i));
}
0
-1 / 25 / 4
Регистрация: 27.11.2017
Сообщений: 375
13.01.2018, 19:38  [ТС]
Ну это все слишком сложно, нам бы что-нибудь попроще, вот так разве нельзя?

C++
1
2
3
4
auto func() -> void*
{
    return &func;
}
0
зомбяк
 Аватар для TRam_
1585 / 1219 / 345
Регистрация: 14.05.2017
Сообщений: 3,940
13.01.2018, 19:58
Просто Саша, кастование из (void *) к указателю на функцию запрещено.

Добавлено через 3 минуты
Нужно кастовать между указателями на функции с разными типами и аргументами. В данном случае в качестве промежуточного используется "функция, которая возвращает указатель на функцию, возвращающую указатель"
0
-1 / 25 / 4
Регистрация: 27.11.2017
Сообщений: 375
15.01.2018, 18:52  [ТС]
Цитата Сообщение от TRam_ Посмотреть сообщение
Нужно кастовать между указателями на функции с разными типами и аргументами. В данном случае в качестве промежуточного используется "функция, которая возвращает указатель на функцию, возвращающую указатель"
Ну, если Вы хотите, то можно спокойно обойтись и без кастования, вот таким вот образом:

C++
1
2
3
4
5
6
typedef auto (*pfunc)() -> auto (*)() -> pfunc;
 
pfunc func()
{
    return &func;
}
P.S. Если хотите, то все круглые скобки можете заполнить любыми наборами аргументов. Главное, чтобы они все соответствовали друг другу, как по типам, так и по порядку следования.
0
зомбяк
 Аватар для TRam_
1585 / 1219 / 345
Регистрация: 14.05.2017
Сообщений: 3,940
15.01.2018, 19:26
Цитата Сообщение от Просто Саша Посмотреть сообщение
вот таким вот образом
На каком из компиляторов это скомпилируется?

Добавлено через 1 минуту
Тогда уж
C++
1
typedef auto (*pfunc)() -> pfunc;
0
-1 / 25 / 4
Регистрация: 27.11.2017
Сообщений: 375
15.01.2018, 19:34  [ТС]
Цитата Сообщение от TRam_ Посмотреть сообщение
На каком из компиляторов это скомпилируется?
Visual Studio 2017

Цитата Сообщение от TRam_ Посмотреть сообщение
typedef auto (*pfunc)() -> pfunc;
А вот так не скомпилируется

Добавлено через 7 минут
Интересно другое, можно ли вообще обойтись без typedef
0
зомбяк
 Аватар для TRam_
1585 / 1219 / 345
Регистрация: 14.05.2017
Сообщений: 3,940
15.01.2018, 19:47
Цитата Сообщение от Просто Саша Посмотреть сообщение
можно ли вообще обойтись без typedef
Нет, т.к. возвращаемый тип (который pfunc) нужно указать в строке декларации.

Добавлено через 5 минут
А вот в gcc последней версии (v7.1.1) всё равно будет ошибка
Bash
1
2
3
4
5
6
7
8
9
10
11
12
$g++ -std=c++1z -o main *.cpp
main.cpp:3:33: error: typedef declared ‘auto’
 typedef auto (*pfunc)() -> auto (*)() -> pfunc;
                                 ^
main.cpp:3:33: error: typedef ‘pfunc’ is initialized (use decltype instead)
main.cpp:3:35: error: expected primary-expression before ‘)’ token
 typedef auto (*pfunc)() -> auto (*)() -> pfunc;
                                   ^
main.cpp:5:1: error: ‘pfunc’ does not name a type; did you mean ‘putc’?
 pfunc func()
 ^~~~~
 putc
0
-1 / 25 / 4
Регистрация: 27.11.2017
Сообщений: 375
15.01.2018, 20:11  [ТС]
Цитата Сообщение от TRam_ Посмотреть сообщение
А вот в gcc последней версии (v7.1.1) всё равно будет ошибка
Насчет gcc ничего сказать не могу, так как не пользуюсь им.

Добавлено через 15 минут
А вообще вы знаете, ошибся я.
Не знаю как проходило, но вот теперь вижу, что не компилируется.
0
зомбяк
 Аватар для TRam_
1585 / 1219 / 345
Регистрация: 14.05.2017
Сообщений: 3,940
15.01.2018, 20:31
C++
1
2
3
4
5
6
7
8
9
10
11
12
typedef auto (*pfunc)() -> void *;
 
pfunc funct()
{
    return reinterpret_cast<pfunc>(&funct);
}
 
int main()
{
    pfunc p_f = funct();
    p_f = reinterpret_cast<pfunc>((*p_f)());
}
1
-1 / 25 / 4
Регистрация: 27.11.2017
Сообщений: 375
15.01.2018, 20:35  [ТС]
Цитата Сообщение от TRam_ Посмотреть сообщение
typedef auto (*pfunc)() -> auto (*)() -> void *;
pfunc funct()
{
* * return reinterpret_cast<pfunc>(&funct);
}
int main()
{
* * pfunc p_f = funct();
* * p_f = reinterpret_cast<pfunc>((*p_f)());
}
Да, уважаемый TRam, ваш пример рабочий.
Главное, что в функции main можно теперь писать вот такие конструктивы

C++
1
funct()()()()()
Чего я в общем и добивался.
0
зомбяк
 Аватар для TRam_
1585 / 1219 / 345
Регистрация: 14.05.2017
Сообщений: 3,940
15.01.2018, 20:44
Думаю, оптимально будет так:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
typedef auto (*pfunc)() -> void *;
// либо так:
// typedef void *(*pfunc)();
 
void *funct()
{
    return reinterpret_cast<void *>(&funct);
}
 
int main()
{
    pfunc p_f = reinterpret_cast<pfunc>(funct());
    p_f = reinterpret_cast<pfunc>((*p_f)());
    p_f = reinterpret_cast<pfunc>((*p_f)());
}
0
-1 / 25 / 4
Регистрация: 27.11.2017
Сообщений: 375
15.01.2018, 20:45  [ТС]
Вообще, ведь если так подумать, то пока не объявлена функция, говорить об указателе на нее бессмысленно, но сама функция для своего объявления требует уже готового типа этого указателя. Получается классическая зациклинность.

Поэтому, считаю, что на данный момент сделать такое ни в C++, ни где-либо ещё в чистом виде абсолютно нереально.
0
зомбяк
 Аватар для TRam_
1585 / 1219 / 345
Регистрация: 14.05.2017
Сообщений: 3,940
15.01.2018, 20:47
А то что нельзя преобразовывать указатель на функцию из void * - моя ошибка...
0
-1 / 25 / 4
Регистрация: 27.11.2017
Сообщений: 375
15.01.2018, 20:47  [ТС]
Цитата Сообщение от TRam_ Посмотреть сообщение
typedef auto (*pfunc)() -> void *;
// либо так:
// typedef void *(*pfunc)();
void *funct()
{
* * return reinterpret_cast<void *>(&funct);
}
int main()
{
* * pfunc p_f = reinterpret_cast<pfunc>(funct());
* * p_f = reinterpret_cast<pfunc>((*p_f)());
* * p_f = reinterpret_cast<pfunc>((*p_f)());
}
Зачем?
Ваш пример работает и в таком формате

C++
1
fumct()()()();
Я проверил.
0
зомбяк
 Аватар для TRam_
1585 / 1219 / 345
Регистрация: 14.05.2017
Сообщений: 3,940
15.01.2018, 20:49
Цитата Сообщение от Просто Саша Посмотреть сообщение
Получается классическая зациклинность
Получается классическая рекурсия, которая в данном случае разрывается преобразованием аргументов функции (у hoggy) или типа указателя (у меня)
0
-1 / 25 / 4
Регистрация: 27.11.2017
Сообщений: 375
15.01.2018, 20:52  [ТС]
Все было бы ништяк, если бы this работал не только для классов, но и для отдельных функций.

Добавлено через 2 минуты
Цитата Сообщение от TRam_ Посмотреть сообщение
А то что нельзя преобразовывать указатель на функцию из void * - моя ошибка...
Да нет у Вас никакой ошибки, все правильно работает.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
15.01.2018, 20:52
Помогаю со студенческими работами здесь

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

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

Определить функцию, которая возвращает расстояние между двумя точками на плоскости
Определить функцию, которая возвращает расстояние между двумя точками на плоскости.Вычислить расстояние между всеми точками с координатами...

Напишите функцию сортировки, похожую на функцию которая использовалась для сортировки массивов, с той разницей, что ее а
Напишите функцию сортировки, похожую на функцию которая использовалась для сортировки массивов, с той разницей, что ее аргументом должен...

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


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

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
Модель заражения группы наркоманов
alhaos 17.04.2026
Условия задачи сформулированы тут Суть: - Группа наркоманов из 10 человек. - Только один инфицирован ВИЧ. - Колются одной иглой. - Колются раз в день. - Колются последовательно через. . .
Мысли в слух. Про "навсегда".
kumehtar 16.04.2026
Подумалось тут, что наверное очень глупо использовать во всяких своих установках понятие "навсегда". Это очень сильное понятие, и я только начинаю понимать край его смысла, не смотря на то что давно. . .
My Business CRM
MaGz GoLd 16.04.2026
Всем привет, недавно возникла потребность создать CRM, для личных нужд. Собственно программа предоставляет из себя базу данных клиентов, в которой можно фиксировать звонки, стадии сделки, а также. . .
Знаешь почему 90% людей редко бывают счастливыми?
kumehtar 14.04.2026
Потому что они ждут. Ждут выходных, ждут отпуска, ждут удачного момента. . . а удачный момент так и не приходит.
Фиксация колонок в отчете СКД
Maks 14.04.2026
Фиксация колонок в СКД отчета типа Таблица. Задача: зафиксировать три левых колонки в отчете. Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка) / / . . .
Настройки VS Code
Loafer 13.04.2026
{ "cmake. configureOnOpen": false, "diffEditor. ignoreTrimWhitespace": true, "editor. guides. bracketPairs": "active", "extensions. ignoreRecommendations": true, . . .
Оптимизация кода на разграничение прав доступа к элементам формы
Maks 13.04.2026
Алгоритм из решения ниже реализован на нетиповом документе, разработанного в конфигурации КА2. Задачи, как таковой, поставлено не было, проделанное ниже исключительно моя инициатива. Было так:. . .
Контроль заполнения и очистка дат в зависимости от значения перечислений
Maks 12.04.2026
Алгоритм из решения ниже реализован на примере нетипового документа "ПланированиеПерсонала", разработанного в конфигурации КА2. Задача: реализовать контроль корректности заполнения дат назначения. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru