Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

typedef'ing function *signature* (not a pointer to), so that it can be reused?

EDIT: MOTIVATION

Suppose I define a Handler class as

class Handler {
public:
  class Message { /*...*/ };
  typedef int (*Callback)(Message *msg);
  void registerCallback(int msgclass, Callback f);
};

A client can do

int f1(Handler::Message *msg)
{ /* handle message */ }

int f2(Handler::Message *msg)
{ /* handle message */ }

int main(){
  Handler h;
  h.registerCallback(1, f1);
  h.registerCallback(2, f2);
  // ....
}

The compiler will indeed check that f1 and f2 are appropriate as parameters to registerCallback, however, it's up to the client to define f1 and f2 correctly. Since I've allready typedefed Callback, I'd like the client to be able to use it instead.

END EDIT

I'd like to do something like this:

typedef int arithmetic(int i, int j);

arithmetic sum
{
 return i+j;
}

arithmetic max
{
  return (i>j)? i:j;
}
// etc.

However, both

arithmetic sum
arithmetic sum()

don't compile, and also this

arithmetic sum(int i, int j)

which gives compiler error of

func.cpp:4: error: ‘sum’ declared as function returning a function

The reason I want this is that I want to have a Handler class which would provide a typedef for a callback function it accepts, including the parameter list.

like image 702
davka Avatar asked Mar 04 '11 14:03

davka


2 Answers

I'll give you a classic C answer, without resorting to the newfangled C++0x toys. Let's start by defining a function prototype:

typedef int TWO_ARG_FUNC(int x, int y);

You can use this prototype when receiving a function pointer, e.g.:

void blah(TWO_ARG_FUNC* funcPtr);

... or when forward-declaring a function:

TWO_ARG_FUNC max;

... but you cannot implement a function by just writing the prototype, e.g.:

TWO_ARG_FUNC max
{
   ... // bzzt, error!
}

However, not all is lost. You can enforce the function to remain true to a prototype by first forward-declaring it:

TWO_ARG_FUNC max;

int max(int a, int b)
{
    ...
}

Another option would be to resort to C macros:

#define DEFINE_TWO_ARG_FUNC(funcName) int funcName(int a, int b)

DEFINE_TWO_ARG_FUNC(max)
{
}

and you can even use the macro to declare a function prototype, in case you later want to declare a pointer to such a function:

typedef DEFINE_TWO_ARG_FUNC(TWO_ARG_FUNC);
like image 56
Ilya Avatar answered Nov 07 '22 10:11

Ilya


First, you did not typedef a signature. A signature is everything that identifies a single function. It contains the namespace/class of the function and so on.

What you typedef'ed is the type of a function. Like when you typedef int inttype which typedefs the type of an int, you typedef'ed the type of a function.

You can use the typedef-name to declare functions only.

arithmetic max; // valid

But it cannot be used to define functions. For defining functions, you need to provide a parameter list literally and manually. Reasons include giving names for parameters (and possibly other, more technical reasons. C++0x introduces arithmetic max {}; which will get a specific initialization meaning).

like image 31
Johannes Schaub - litb Avatar answered Nov 07 '22 12:11

Johannes Schaub - litb