开发者

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;开发者_如何学Go
}

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.


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


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).


Thinking about your post I will give it a shot about what you want to archive. You could try using boost or C++0x lambda. I will go with boost.

typedef boost::function<int(int,int)> arithmetic;
arithmetic sum = (boost::lambda::_1 + boost::lambda::_2);
arithmetic max = boost::lambda::if_then_else_return(boost::lambda::_1 > boost::lambda::_2,
    boost::lambda::_1, boost::lambda::_2);

int j = sum(3,3); // j ist 6
int k = max(4,2); // k is 4

So maybe this is what you want to archive.

It is also possible with a full blown function. Here you go.

int FullBodyFunction(int i, int j)
{
    return i+j;
}
arithmetic sum2 = boost::bind(&FullBodyFunction, _1, _2);

This will do the same as sum1. You are free to use the whole boost bind stuff. E.g. bind to method of a object or what ever you want.


Since, as you say, you can use C++0x, you might choose to do something like this by typedef'ing a function:

edit, added in your concept of a handler class containing a callback typedef:

#include <functional>
#include <list>

int max(int a, int b)
{
    return (a>=b) ? a : b;
}

class Handler
{
    public:

        //typedef int (*Callback)(int, int);
        typedef std::function<int (int, int)> Callback;

        void add(Callback func) { functions_.push_back(func); }

    private:

        std::list<Callback> functions_;
};

int main(int argc, char* argv[])
{
    Handler handler;

    handler.add([](int a, int b) -> int { return (a>=b) ? a : b; });
    handler.add(max);

    return 0;
}

This isn't the exact syntax you're looking for, but as others have pointed out, it isn't possible to use typedef for a function signature directly.


I haven't find solution with exact syntax you are looking for, but something like this works:

#include <cassert>

#define  arithmetic (int i, int j) -> int

#define declare(Func, Name) auto Name Func

#define as_

auto sum as_ arithmetic
{
  return i + j;
};

declare(arithmetic, max)
{
  return (i>j) ? i : j;
};

int main()
{
  assert(sum(2, 4) == 6);
  assert(max(2, 4) == 4);

  return 0;
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜