P Shved
P Shved

Reputation: 99344

Can I declare a function that can take pointer to itself as an argument?

Reading a question in stackoverflow, I wondered whether it's possible to declare a function that takes a pointer to itself. I.e. to make such declaration of foo, for which the following would be correct:

foo(foo);

The simpliest idea is casting to another function pointer (can't cast to void*, since it may be smaller), so the function declaration looks like this:

void foo(void (*)());

While that's OK in C (and will work with casting in C++), I wonder, whether it can be done without such hard "reinterpret" casting or losing type information.

In other words, I want the following declaration:

void foo( void (*)( void (*)( void (*) ( ... ))));

but, of course, unlimited declarations are impossible. Naive typedefing doesn't help either.

C++ templates are welcome, even if they make the calling code (foo(foo)) look a bit less succinct, but still finite.

C-style answers that show, how one can drop type information without casting, or other tricks of that sort are, of course, interesting, but won't be accepted.

Upvotes: 11

Views: 4338

Answers (8)

sdcvvc
sdcvvc

Reputation: 25654

Generally I agree with Dario - making this on type level seems impossible.

But you can use classes ("strategy pattern"):

class A {
  void evil(A a) {       // a pointer to A is ok too
  }
};

You can even add operator():

  void operator()(A a) { return evil(a); }

Generally such things are better done in FP languages. Haskell version is simply:

data Evil = Evil (Evil -> Integer)

This uses a wrapper (Evil) that corresponds to using a class.

From the questioner: what this answer lacked was the ability to pass several different functions as an argument of one of them. This can be solved either by making evil() virtual or by explicitly storing in the object a function pointer that implements it (which is basically the same).

With this clarification, the answer is good enough to be accepted.

Upvotes: 3

Vadakkumpadath
Vadakkumpadath

Reputation: 1485

Another dirty trick.

void Foo( ... )
{
}

int main()
{
 Foo( Foo );
}

Above program will compile without any error. But it is not recursive. Following modified function is recursive version with a limiter.

#define RECURSIVE_DEPTH (5)

typedef void ( *FooType )( int, ... );

void Foo( int Depth, ... )
{
 void ( *This )( int, ... );

 va_list Arguments;

 va_start( Arguments, Depth );

 if( Depth )
 {
  This = va_arg( Arguments, FooType );

  This( Depth - 1, This );
 }

 va_end ( Arguments );  
}

int main()
{
 Foo( RECURSIVE_DEPTH, Foo );
}

Upvotes: 5

MSalters
MSalters

Reputation: 179981

YES

It's a variant of "Can you write a function that returns a pointer to itself?", except that in your case, the function type recursively appears as an argumkent, not as the return type. Herb Sutters answer is reusable, though: wrap the pointer in a forward-declared proxy class.

Upvotes: 4

ZachS
ZachS

Reputation: 1248

I don't believe you can have a function that can take itself as an argument in C++ without some kind of trickery, such as putting your function in a class, and having the function take that class as an argument.

Another way that will be possible once the new C++ standard hits is to use lambdas, and have the lambda capture itself. I think it would go something like this:

auto recursive_lambda = [&recursive_lambda] { recursive_lambda(); };

Be warned that such a statement is totally untested in any compiler that supports lambdas. Your mileage may vary.

Upvotes: 1

Christoph
Christoph

Reputation: 169673

A related problem is returning a function pointer of same type. It comes up when implementing state machines, so it got its own entry in the C FAQ.

The same workarounds can be applied to your problem.

Upvotes: 2

newacct
newacct

Reputation: 122489

If a function could take itself as an argument, then it could perform anonymous recursion by calling itself. But recursion is impossible in simply-typed lambda calculus (which is basically what you have here, with function types). You need to implement a fixed-point combinator using recursive functions or recursive types in order to perform anonymous recursion.

Upvotes: 0

DigitalRoss
DigitalRoss

Reputation: 146123

This is a perfectly valid use of void *.

typedef void T(void *);

void f(T *probably_me)
{
  (*probably_me)(f);
}

Upvotes: 0

Dario
Dario

Reputation: 49218

Apparently not - see this thread. The type required here would always be infinite.

Upvotes: 5

Related Questions