Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Any way in C++ to forward declare a function prototype?

I make regular use of forward class declarations and pointers to such classes.

I now have a need to pass a function pointer through a number of layers. I would prefer to include the header that declares my function pointer's prototype only into the module that dereferences a function pointer rather than into each layer that simply passes along that pointer value.

Is this possible?

=====

From the replies I suspect that I have not expressed by question clearly enough. I seek an analog to a forward class declaration. We all agree that I can write:

class foo;

void bar(foo*);

void waz(foo* p) { bar(p); }

Notice that waz knows nothing about class foo other than its name. Perhaps bar will have access to foo's complete description. Perhaps bar will simply pass p further along. Who cares? Only those sites that dereference a foo*. All other sites need only "class foo;".

Similarly I know that I can write:

typedef void foo(int, double);

void bar(foo*);

void waz(foo* p) { bar(p); }

The difference is that now the identifier foo not only is known to denote a function type but further already carries the full signature/prototype. This forces me into one of two unpleasant scenarios:

1) clone the typedef at multiple sites (yuck! fragile!) 2) stick the typedef in a header and include it everywhere that a foo* is mentioned.

Notice the asymetry: in the case of a data object I only needed to provide a complete description of class foo at those points where I want to dereference a foo*; in the case of a function I need to provide the full signature/prototype everywhere I want to mention a foo*.

So is there anyway to remedy this asymmetry?

like image 977
John Yates Avatar asked Apr 04 '10 03:04

John Yates


People also ask

How do you forward a function declaration?

To write a forward declaration for a function, we use a function declaration statement (also called a function prototype). The function declaration consists of the function header (the function's return type, name, and parameter types), terminated with a semicolon. The function body is not included in the declaration.

Can you forward-declare in C?

In Objective-C, classes and protocols can be forward-declared like this: @class MyClass; @protocol MyProtocol; In Objective-C, classes and protocols can be forward-declared if you only need to use them as part of an object pointer type, e.g. MyClass * or id<MyProtocol>.

Can you forward-declare a struct?

Basically, you never need to forward declare struct b on its own, because it always declares the partial type on the line itself when you use it to perform a pure declaration, so this is redundant code. The only benefit of this type of forward declaration is it can be used with a typedef.

How do you perform a forward declaration of a subroutine performed?

To declare a subroutine, use one of these forms: sub NAME ; # A "forward" declaration. sub NAME ( PROTO ); # Ditto, but with prototype.


2 Answers

You can do this using an undefined structure type, at the cost of an extra dereference.

put this in the main header file:

typedef struct FuncStruct *FuncPtr;

This declares struct FuncStruct but does not declare any fields, then it declares a pointer to this struct called FuncPtr. You can pass FuncPtrs around but you can not dereference them.

then in a particular file (or a more specific .h file), you can actually define a struct FuncStruct like this:

struct FuncStruct {
  int (*f)(int, char, double);
};

Then code past this definition can dereference a FuncPtr to get the actual function pointer.

Note this is an extra dereference from just a cast, and it means you'll need to do some memory management of FuncStructs.

like image 124
Keith Randall Avatar answered Oct 13 '22 09:10

Keith Randall


For passing function pointers you only need to know the argument types and the return type:

void f(void (*func)(int));

Here, f() is a function that takes a function pointer to a function that takes an int and returns void.

typedefs make that more readable:

typedef void (*FuncPtr)(int);
void f(FuncPtr func);

In general you might want to look at functors or using e.g. Boost.Function and Boost.Bind. That way you can also pass in bound member functions or function objects:

void f(boost::function<void (int)> fn) {
    fn(42);
}

struct X {
    void f(int) {}
};

// ...
X x;
f(boost::bind(&X::f, &x, _1));
like image 37
Georg Fritzsche Avatar answered Oct 13 '22 10:10

Georg Fritzsche