2

i want to achieve an C# like Event Handling in Standard C++ (UNIX) like the following Code:

public class connection{

    public delegate void Message(object sender, string text);
    public event Message doMessage = null;

    //called from within a Thread or something alike
    private void MessageReceived(string Message){
        if (this.doMessage != null)
        {
            this.doMessage(this, Message);
        }
    }
}

public class Main{
    Connection con;

    public Main()
    {
        this.con = new Connection();
        this.con.doMessage += con_doMessage;
    }

    void con_doMessage(object sender, string message)
    {
        txtMain.Text = txtMain.Text + Environment.NewLine + message;
    }
}

I googled my fingertips bloody but all i found was Events firing, but not to an overlaying class like in my Example.

In fact, i'm new to Standard C++, maybe there is an easy way to get Data to the overlaying class, by firing it from within the class and i just didn't see it yet.

But yeah, as said, i have no clue and would be thankfull for some advice.

Da Maex
  • 481
  • 7
  • 27

3 Answers3

8

Use std::function as a callback:

void printSomething() { std::cout << "event!" << std::endl; }

int main() {
    std::function<void()> onEvent;
    onEvent = &printSomething;
    onEvent(); // prints "event!"
}

If you want C#-style delegates, use std::vector<std::function<...>>:

struct Delegate {
    std::vector<std::function<void()>> funcs;
    template<class T> Delegate& operator+=(T mFunc) { funcs.push_back(mFunc); return *this; }
    void operator()() { for(auto& f : funcs) f(); }
};

int main() {
    Delegate delegate;
    delegate += []{ std::cout << "hello, "; };
    delegate += []{ std::cout << "world!" << endl; };
    delegate(); // prints "hello, world!"
}

Or just copy my ssvu::Delegate class, available here.

Vittorio Romeo
  • 90,666
  • 33
  • 258
  • 416
  • Yeah, things like this i found, but how do i fire the Event from, in my example, within the connection class, and get the Handler in my Main Class to receive the data? – Da Maex Oct 15 '13 at 13:52
  • 1
    Can't you have the `Delegate delegate;` object in the `Connection` class, make it `public` and use it both from the class itself and both from the main function? – Vittorio Romeo Oct 15 '13 at 13:54
  • This sounds like an Idea, gonna try this! – Da Maex Oct 15 '13 at 13:57
0

This is relevant, or the same, with a very recent question. You can check my answer there. In short, a more complete/tested solution than building you own infrastructure may be Boost.Signals2.

Community
  • 1
  • 1
iavr
  • 7,547
  • 1
  • 18
  • 53
0

Using std::function will probably be enough for almost all of your use-cases. In case you really need multiple event receivers, have a look at the multifunction (multicast delegate) proof of concept I wrote.

It allows you to write code that is syntactically similar to C#:

void f(int n) { cout << "f: " << n << "\n"; }

util::multifunction<void(int)> event;

event += f;
event += [](int n) { cout << "[]: " << n << "\n"; };

event(42);
Konrad Rudolph
  • 530,221
  • 131
  • 937
  • 1,214