1

Тема: Функція, що повертає вказівник на саму себе

Завжди цікавило питання, як правильно оголошувати функцію, що повертає вказівник на саму себе (чи на іншу функцію з таким же набором параметрів і результатом).

Подякували: Yola, leofun012

2

Re: Функція, що повертає вказівник на саму себе

Повертайте об'єкт, що вміє operator().

Подякували: leofun011

3 Востаннє редагувалося P.Y. (23.02.2018 18:06:24)

Re: Функція, що повертає вказівник на саму себе

Це в плюсах, і це незовсім те — зайва надбудова. А як щодо чистого Сі?

Подякували: leofun011

4 Востаннє редагувалося koala (23.02.2018 21:09:22)

Re: Функція, що повертає вказівник на саму себе

У чистих плюсах сях без додаткових перетворень - ніяк.
Вибачте, описка.

5

Re: Функція, що повертає вказівник на саму себе

koala написав:

У чистих плюсах без додаткових перетворень - ніяк.

Є пам'ять, є прототип об'єкту, є приведення типу.Що ще потрібно, я не розумію.Чи я не розумію філософію хрестів ?

6

Re: Функція, що повертає вказівник на саму себе

Тупа помилка, вибачте.
Прототипу функції немає.

7

Re: Функція, що повертає вказівник на саму себе

P.Y. написав:

Завжди цікавило питання, як правильно оголошувати функцію, що повертає вказівник на саму себе (чи на іншу функцію з таким же набором параметрів і результатом).

Максимум, що зміг витиснути з C (без структур) :

#include<stdio.h>

typedef void *(*fptr_type)(int);

void *func(int n) { printf("\r\n %i", n); return func; }

int main() {
    printf("\r\n start");
    fptr_type f = (fptr_type)func;
    for(int i = 0; i < 5; ++i) {
        f = (fptr_type)f(i);
    }
    printf("\r\n ------");
    (fptr_type)((fptr_type)((fptr_type)func(0))(1))(2);
    printf("\r\n finish");
}
Подякували: koala, ReAl2

8

Re: Функція, що повертає вказівник на саму себе

Тобто, зрештою, повертає вказівник не «на себе», потрібні приведення.
Навіть якщо повертатиме fptr_type, однак це буде не на свій тип.
А на свій тип то буде дурна нескінченість оголошення.

Подякували: leofun011

9 Востаннє редагувалося Yola (25.02.2018 10:53:20)

Re: Функція, що повертає вказівник на саму себе

P.Y. написав:

Завжди цікавило питання, як правильно оголошувати функцію, що повертає вказівник на саму себе (чи на іншу функцію з таким же набором параметрів і результатом).

У цьому нема практичної потреби, бо якщо ви можете викликати функцію, то ви можете і вказівник отримати без того, щоб її викликати.

Якщо сильно хочеться в один рядок, то можна так:

template <typename Fun, typename... Args>
Fun& call_and_return_pointer(Fun &&f, Args&&... args) {
    f(std::forward<Args>(args)...);
    return f;
}

void foo(int i) { cout << "free function: " << i << endl; }

struct S {
    void operator()(int i) { cout << "functor: " << i << endl; }
};

int main() {
    call_and_return_pointer(foo, 1)(1);
    call_and_return_pointer(S(), 1)(1);
    return 0;
}

10

Re: Функція, що повертає вказівник на саму себе

Yola написав:
P.Y. написав:

оголошувати функцію, що повертає вказівник на саму себе (чи на іншу функцію з таким же набором параметрів і результатом).

У цьому нема практичної потреби, бо якщо ви можете викликати функцію, то ви можете і вказівник отримати без того, щоб її викликати.

*WALL*

11

Re: Функція, що повертає вказівник на саму себе

koala написав:

*WALL*

Відповіді такого типу роблять з replace смітник.

P.Y. хоче, щоб функція повертала вказвіник на себе, я правильно зрозумів? Якщо так, то навіщо це треба? Адже, якщо я можу викликати функцію, то я можу і вказвіник на неї отримати, мені для двох ций дій потрібно два рядки коду. Що саме не так з моєю відповіддю.

12

Re: Функція, що повертає вказівник на саму себе

Така функція може повертати вказівник на себе, вказівник на іншу функцію такого ж типу, або NULL.
Практичний сенс — насправді просто подивитися, чи це можливо. Теоретично, такі функції можна використати, наприклад, як будівельний матеріал для організації хвостової рекурсії (подібно до механізму trampoline в мові Clojure, де функція повертає хвостовий виклик у вигляді функції-результату), для організації черги подій тощо — проте, оскільки в Сі немає замикань, можливості таких функцій, що повертають функції, доволі обмежені, або замість вказівника на функцію треба повертати щось складніше — структуру, яка міститиме вказівник на функцію та додаткові дані.

Подякували: koala, leofun01, Yola3

13

Re: Функція, що повертає вказівник на саму себе

Yola написав:
koala написав:

*WALL*

Відповіді такого типу роблять з replace смітник.

Я спеціально виділив рядок в початковій умові, на який звертав вашу увагу. Але ви його тут навіть не процитували.

Yola написав:

P.Y. хоче, щоб функція повертала вказвіник на себе, я правильно зрозумів?

P.Y. вже відповів дуже детально. Мова йде про тип функції, а не про конкретно цю функцію.

14 Востаннє редагувалося Yola (26.02.2018 08:04:51)

Re: Функція, що повертає вказівник на саму себе

P.Y. написав:

Теоретично, такі функції можна використати, наприклад, як будівельний матеріал для організації хвостової рекурсії (подібно до механізму trampoline в мові Clojure, де функція повертає хвостовий виклик у вигляді функції-результату), для організації черги подій тощо...

Щодо хвостової рекурсії, то її можна зробити в С і без повертання вказівника. А якщо ви й повернете вказівник, то як ви запустите рекурсію? Можливо для реалізації черги подій, я не знаю як саме ви хочете щоб ця черга функціонувала, в С теж можуть бути природні засоби. Тому я досі вважаю, що нема практичної потреби в повертанні вказівника на свій тип функцією, окрім як просто подивитись).

15 Востаннє редагувалося P.Y. (26.02.2018 13:43:41)

Re: Функція, що повертає вказівник на саму себе

Yola написав:

А якщо ви й повернете вказівник, то як ви запустите рекурсію?

Очевидно, потрібна допоміжна функція, яка викликає дану функцію, отримує результат-вказівник, викликає фукнкцію за вказівником, і т.д., доки не дійде до NULL.

Yola написав:

Щодо хвостової рекурсії, то її можна зробити в С і без повертання вказівника.

В найпростішому випадку (коли функція робить хвостовий виклик лише самої себе), це легко зводиться до циклу. Але якщо в нас є дві функції чи більше, які роблять хвостові виклики себе та одна одна одної, то одна з можливих реалізацій — це описаний вище варіант.

16

Re: Функція, що повертає вказівник на саму себе

P.Y. написав:
Yola написав:

А якщо ви й повернете вказівник, то як ви запустите рекурсію?

Очевидно, потрібна допоміжна функція, яка викликає дану функцію, отримує результат-вказівник, викликає фукнкцію за вказівником, і т.д., доки не дійде до NULL.

Тобто, буде потрібен цикл в цій допоміжній функції?

P.Y. написав:
Yola написав:

Щодо хвостової рекурсії, то її можна зробити в С і без повертання вказівника.

В найпростішому випадку (коли функція робить хвостовий виклик лише самої себе), це легко зводиться до циклу. Але якщо в нас є дві функції чи більше, які роблять хвостові виклики себе та одна одна одної, то одна з можливих реалізацій — це описаний вище варіант.

Будь-яка рекурсія зводиться до циклу, навіть якщо на кожній ітерації є необхідність вибирати, яку функцію викликати. Під словом будь-яка, я маю на увазі не хвостову рекурсію також, просто для хвостової не потрібна додаткова пам'ять.

17

Re: Функція, що повертає вказівник на саму себе

Yola написав:

Тобто, буде потрібен цикл в цій допоміжній функції?

Саме так.

18 Востаннє редагувалося Yola (26.02.2018 14:58:47)

Re: Функція, що повертає вказівник на саму себе

стандарт написав:

Точка оголошення для імені - одразу після його повного проголошувача (declarator).  [basic.scope.pdecl]

Отже ви не можете використати тип який ви ще не оголосили до кінця оголошувача, а саме до символа ;. Тобто, відповідь ні, таку функцію оголосити не можливо.

19

Re: Функція, що повертає вказівник на саму себе

Проте, в Сі елементи структури можуть бути вказівниками на цю ж структуру (чи на інший тип, що оголошується пізніше) — це необхідно для організації списків, дерев тощо.

Подякували: leofun011

20 Востаннє редагувалося Yola (27.02.2018 13:29:58)

Re: Функція, що повертає вказівник на саму себе

P.Y. написав:

Проте, в Сі елементи структури можуть бути вказівниками на цю ж структуру (чи на інший тип, що оголошується пізніше) — це необхідно для організації списків, дерев тощо.

стандарт написав:

Точка оголошення для injected-class-name одразу після дужок, що відкривають визначення класу.

Такі два шматки коду тотожні:

// 1.
class A { ... };
// 2.
class A; // Ім'я проголошено
class A { ... };

Важливо, що коли ми використовємо ім'я, то ім'я вже проголошено, а у вашому випадку треба використати ім'я яке ще не проголосили. Фактично ім'я всередині самого себе, а це порушує аксіому регулярності.