1

I am working on a little project containing simple server which listens to messages.

Assuming we have the following classes:

class Message;

class Server
{
    void handler1(Message msg);
    void handler2(Message msg);
    .
    .
    .
    void handler19(Message msg);
};

Can i create a new function type of the class Server that returns void and gets a single Message variable called msg like this:

typedef void(Server::*MessageHandler)(Message msg);

So the class declaration would be:

class Server
{
    MessageHandler handler1;
    .
    .
    .
    MessageHandler handler19;
}

A thing as mentioned would come handy with sqlite3 callback functions (where the function declaration is not the cleanest).

If it is possible, how can i implement such function?

If this is not possible, is there any similar way of making the code more simple (like C# delegates)?

Thank you in advance!

iYehuda
  • 25
  • 3

1 Answers1

0

For the code:

class Server {
    void handler1(Message msg); // This declares a method named handler one which takes a Message and returns void
    void(Server::*handler)(Message); // This declares a member variable named handler of the type Server method pointer to a method that takes a Message and returns a void
};

handler can be reassigned with any Server method which takes a Message and returns void. But it must be initialized before it is first used; something like: handler = handler1 at this point a call to handler would be a call to handler1. But handler could then be reassigned at will, for example if you did: handler = handler2 at this point a call to handler would be a call to handler2.

I wasn't sure from your question if you understood, but handler never defines a method; only a pointer to one.

Given this definition of Server:

class Server {
    void Handler1(int param) { cout << param + 1 << endl; }
    void Handler2(int param) { cout << (param << 1) << endl; }
    void Handler3(int param) { cout << (param != 0 ? "true\n" : "false\n"); }
    void Handler4(int param) { cout << static_cast<char>(param + 'A') << endl; }
public:
    function<void(Server, int)> handler_;
    void next() {
        if (!handler_ || *handler_.target<void (Server::*)(int)>() == &Server::Handler4) {
            handler_ = &Server::Handler1;
        } else if(*handler_.target<void (Server::*)(int)>() == &Server::Handler1) {
            handler_ = &Server::Handler2;
        } else if (*handler_.target<void (Server::*)(int)>() == &Server::Handler2) {
            handler_ = &Server::Handler3;
        } else {
            handler_ = &Server::Handler4;
        }
    }
};

You could do the following:

Server foo;

for (auto i = 'A'; i <= 'Z'; ++i) {
    foo.next();
    foo.handler_(foo, i);
}

Live Example

Jonathan Mee
  • 37,899
  • 23
  • 129
  • 288