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