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 typedef
ed 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;
}
精彩评论