Function pointer pointing to a function that takes

2019-01-25 12:14发布

问题:

How do I declare a function pointer that points to a function taking the same function pointer as the argument?

I've tried the following without success:

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

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

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

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

Is this possible?

回答1:

I very much doubt it, but you can get the needed recursion by introducing a struct.

struct Rec;

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

struct Rec {
    RecFun fun;
};

Example of use:

#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);
}

Update: As per the suggestions of Chris, Vitus, and Johannes, here are some convenient implicit conversions (as in Herb Sutter's GotW #57):

struct Rec;

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

struct Rec {
    RecFun fun;
    Rec(RecFun fun) : fun(fun) {}
    operator RecFun() const { return fun; }
};


回答2:

Alas, it cannot be done. It would be nice if you could use typename to forward declare a typedef; something like:

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

but that does not work, because typename is restricted to a few specific template uses



回答3:

The easiest way is to just typedef both. A function pointer is a parameter just like any other type:

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

Edit: Folks have pointed out you mean both to be the same type. In that case, it's not possible, as the type would be recursive. It's impossible to create a complete type specification (the type of the function's parameter is never completely specified, ergo...)



回答4:

it is possible in this way:

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

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

void func2(fn2)
{
/* ... */
}
void main()
{
fnptr fn = &func;
func2(fn);
}


回答5:

You can also defeat the type system by pretending that the function takes some other function pointer type, and then casting it when you pass something to the function and inside the function to get the original type back.

Not recommended obviously, but just putting it out there.

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);
}