0

I'm working on a library that's based upon a simple event-system.

For work with GUI elements ("controls"), these are needed a lot. For example, the Window class has got a bunch of events, like "onMouseMove", "onKeyPress", "onKeyRelease", .. However, the basic class for controls is the Control class. It has a virtual function draw (which obviously draws the control) and a virtual function connect which connects the control's and the main window's events (works similar to the Qt Signal-Slot-Concept).

But since the Event class takes an std::function<...> pointer as subject (=> Slot), I cannot simply connect a member function of a derived control class with an event of the window. As a workaround, I'm doing the following thing:

class A : public Control {
    friend class Window;

    public:
        A(){
            this->eventHandler = [this] () -> void {
                 if ( someCondition ) this->onSomeCondition.notify();
            };
        }

        Event<> onSomeCondition;

    protected:
        std::function<void()> eventHandler;

        void connect(Window *window){
            window->onSomeHigherEvent.attach(&this->eventHandler);
        }

        void draw(...) const{

            drawSome(...);

        }

};

What this basically does is that it assigns a lambda function to the std::function<...> in the constructor and attaches that std::function<...> to the chosen event.

There is a major problem though: What happens if I instantiate a few more objects of that class? If I had the event handlers specified in the class, as a normal function like so:

void eventHandler() {
    if ( someCondition ) this->onSomeCondition.notify();
}

And could assign that function to the std::function<...> using std::bind, which does not work for some reason, at least as long as I'm using the following call:

std::bind(&A::eventHandler, this, std::placeholders::_1); // *this will not work since that's just a (reference to the?) copy to of the object.

Anyways, the lambda-function-workaround seems to be less time efficient since it's not really built into the class. Is there a more efficient way to solve this problem? Maybe not by solving the lambda-function problem in particular but by changing the concept?

  • "this will not work for some reason," is a pretty useless error report for establishing what might actually be wrong. – Edward Strange Mar 18 '13 at 16:48
  • I personnally wrote a signal-slot like system for a particle system named [SPARK 2](http://spark.developpez.com/index.php?lang=en) (it is not totally done now). Goal was also to be compatible with C++03 compilers, so I have done it by using pointer-to-members and pointers to objects. Probably more memory friendly than lambdas, and ultra-fast because it was using a lot of templates (function pointers as template parameters, for example). – Synxis Mar 18 '13 at 16:50

1 Answers1

2

I'm not sure what your asking, since I can't find the question, but ...

std::bind(&A::eventHandler, this, std::placeholders::_1); // *this will not work since that's just a (reference to the?) copy to of the object.

This creates a callable object that has one unbound parameter, i.e. it expects to be called with one argument, which is not compatible with std::function<void()> because that is a function that expects to be called with no arguments. It's also not compatible with the eventHandler member function you show, because that too takes no arguments.

Maybe you just want to use std::bind(&A::eventHandler, this);

Jonathan Wakely
  • 166,810
  • 27
  • 341
  • 521
  • Oh yeah sorry that was totally out of context.. Of course this expects one parameter (which was given in the actual program) but the actual problem is to bind the function in the current object's context, respectively `this`. When binding either `this` or `*this` (-> a copy(!) of the contents of `this`), g++ throws a large error message and terminates. –  Mar 18 '13 at 20:18
  • 1
    So update the question to show the error message, and a complete example, or people are making wild guesses with no context. Using `this` with `std::bind` works fine, so you must be doing something wrong. Fix that and you don't need to worry about _"seems to be less time efficient since it's not really built into the class"_ whatever that means. – Jonathan Wakely Mar 18 '13 at 23:06