Указатель на функцию, указывающий на функцию, которая принимает указатель на функцию - PullRequest
7 голосов
/ 25 мая 2011

Как мне объявить указатель на функцию, которая указывает на функцию, принимающую тот же указатель на функцию в качестве аргумента?

Я безуспешно пробовал следующее:

typedef void (*fnptr)(void (*)());

void func(fnptr)
{
    /* ... */
}

void func2(fnptr)
{
    /* ... */
}

void main()
{
    fnptr fn = &func;
    func2(fn);
}

возможно

Ответы [ 5 ]

13 голосов
/ 25 мая 2011

Я очень сильно сомневаюсь в этом, но вы можете получить необходимую рекурсию, введя структуру.

struct Rec;

typedef void (*RecFun)(const Rec&);

struct Rec {
    RecFun fun;
};

Пример использования:

#include <iostream>

void nothing(const Rec& rec) {}
Rec recNothing = { nothing };

void f(const Rec& rec)
{
    std::cout << "f\n";
    rec.fun(recNothing);
}
Rec recF = { f };

void g(const Rec& rec)
{
    std::cout << "g\n";
    rec.fun(recNothing);
}
Rec recG = { g };

int main()
{
    recF.fun(recG);
}

Обновление: Согласно советам Криса, Витуса и Йоханнеса, вот несколько удобных неявных преобразований (как в GotW # 57 от Херба Саттера):

struct Rec;

typedef void (*RecFun)(const Rec&);

struct Rec {
    RecFun fun;
    Rec(RecFun fun) : fun(fun) {}
    operator RecFun() const { return fun; }
};
0 голосов
/ 14 июня 2012

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

Очевидно, не рекомендуется, но просто выкладываю это туда.

typedef void (*fnptr)(void (*)());

void func(void (*x)())
{
    fnptr f = (fnptr)x;
    /* ... */
}

void func2(void (*x)())
{
    fnptr f = (fnptr)x;
    /* ... */
}

void main()
{
    fnptr fn = &func;
    func2((void (*)())fn);
}
0 голосов
/ 13 июня 2012

можно так:

typedef void (*fnptr)(void (*)());

fnptr fn1,fn2;
void func(fn1)
{
/* ... */
}

void func2(fn2)
{
/* ... */
}
void main()
{
fnptr fn = &func;
func2(fn);
}
0 голосов
/ 25 мая 2011

Увы, это невозможно сделать. Было бы неплохо, если бы вы могли использовать typename для прямого объявления typedef; что-то вроде:

typename fnptr;
typedef (*fnptr)(fnptr);

но это не работает, потому что typename ограничен несколькими конкретными шаблонами использования

0 голосов
/ 25 мая 2011

Самый простой способ - просто определить оба. Указатель на функцию является параметром, как и любой другой тип:

typedef (* InnerFunctionPtr)(void);
typedef (* OuterFunctionPtr)(InnerFunctionPtr);

Редактировать: Люди указали, что вы имеете в виду, что оба они одного типа. В этом случае это невозможно, так как тип будет рекурсивным. Невозможно создать полную спецификацию типа (тип параметра функции никогда не указывается полностью, поэтому ...)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...