Skip to content

Conversation

@arturoc
Copy link
Member

@arturoc arturoc commented Feb 4, 2016

ofEvent now supports adding std::function as a listener, that allows among other things:

  • pass a lambda function as a listener
  • pass a function with a different signature as a listener.

For example to pass a lambda as a listener now you can do:

ofEvents().mouseMoved.newListener([](ofMouseEventArgs & mouse){
    cout << mouse << endl;
});

Since std::function doesn't have an equality operator, there's no way to
unregister an event the old way calling ofRemoveListener(function) since
that required to compare the passed function with every other registered in
the event and remove it if it was the same.

ofRemoveListeneralso has some other problems, for example, the typical pattern:

class MyClass{
public:
    MyClass(){
         ofAddListener(ofEvents().mouseMoved,this,&MyClass::mouseMoved);
    }

    ~MyClass(){
         ofRemoveListener(ofEvents().mouseMoved,this,&MyClass::mouseMoved);
    }

    void mouseMoved(ofMouseMoved & mouse){
    ....
    }
}

Has a problem with copy construction:

MyClass obj;
vector<MyClass> objs;
objs.push_back(obj);

Won't be registered as listener and there won't be any compiler error.
Because of the rule of three
Any class that adds a listener in it's constructor and unregisters
in it's destructor. Needs also a copy constructor, operator=, and in
c++11 to be completely correct also a move constructor and an operator=
with move parameter.

With the new way of registering listeners one does:

class MyClass{
    ofEventListener mouseMovedListener;
public:
    MyClass(){
         mouseMovedListener = ofEvents().mouseMoved.newListener(this,&MyClass::mouseMoved);
    }

    void mouseMoved(ofMouseMoved & mouse){
    ....
    }
}

The ofEventListener class unregisters the event automatically when it goes out
of scope avoiding the need for a destructor and because of that avoiding the
need for copy constructor...

Also since the class is not copyable if someone tries to copy an instance
of a class that contains an ofEventListener the compiler will give an error.

In any case the old method still works.

among other things:

- pass a lambda function as a listener
- pass a function with a different signature as a listener.

For example to pass a lambda as a listener now you can do:

```cpp
ofEvents().mouseMoved.newListener([](ofMouseEventArgs & mouse){
	cout << mouse << endl;
});
```

Since std::function doesn't have an equality operator, there's no way to
unregister an event the old way calling `ofRemoveListener(function)` since
that required to compare the passed function with every other registered in
the event and remove it if it was the same.

`ofRemoveListener`also has some other problems, for example, the typical pattern:

```cpp
class MyClass{
public:
    MyClass(){
         ofAddListener(ofEvents().mouseMoved,this,&MyClass::mouseMoved);
    }

    ~MyClass(){
         ofRemoveListener(ofEvents().mouseMoved,this,&MyClass::mouseMoved);
    }

    void mouseMoved(ofMouseMoved & mouse){
    ....
    }
}
```

Has a problem with copy construction:

```
MyClass obj;
vector<MyClass> objs;
objs.push_back(obj);
```

Won't be registered as listener and there won't be any compiler error.
Because of the [rule of three](https://en.wikipedia.org/wiki/Rule_of_three_%28C%2B%2B_programming%29)
Any class that adds a listener in it's constructor and unregisters
in it's destructor. Needs also a copy constructor, operator=, and in
c++11 to be completely correct also a move constructor and an operator=
with move parameter.

With the new way of registering listeners one does:

```cpp
class MyClass{
    ofEventListener mouseMovedListener;
public:
    MyClass(){
         mouseMovedListener = ofEvents().mouseMoved.newListener(this,&MyClass::mouseMoved);
    }

    void mouseMoved(ofMouseMoved & mouse){
    ....
    }
}
```

The ofEventListener class unregisters the event automatically when it goes out
of scope avoiding the need for a destructor and because of that avoiding the
need for copy constructor...

Also since the class is not copyable if someone tries to copy an instance
of a class that contains an ofEventListener the compiler will give an error.

In any case the old method still works.
arturoc added a commit that referenced this pull request Feb 5, 2016
std::function listeners for ofEvent + unregister token. Replaces #4392
@arturoc arturoc merged commit fbcd71c into openframeworks:master Feb 5, 2016
@arturoc arturoc deleted the feature-lambdaevents branch February 5, 2016 10:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant