Event-listener implementation While writing a C++ GUI application more or less from scratch I needed some form of an event-listener system, preferably using lambdas. An event should be able to have multiple listeners and the user should not have to worry about the lifetime of the objects. I came up with this bit using shared and weak pointers to determine object lifetime:

#include &lt;functional&gt;
#include &lt;list&gt;


template &lt;typename ... Args&gt; struct event:public std::shared_ptr&lt;std::list&lt;std::function&lt;void(Args...)&gt;&gt;&gt;{

  using handler = std::function&lt;void(Args...)&gt;;
  using listener_list = std::list&lt;handler&gt;;

  struct listener{
    std::weak_ptr&lt;listener_list&gt; the_event;
    typename listener_list::iterator it;

    listener(){ }

    listener(event &amp; s,handler f){
      observe(s,f);
    }

    listener(listener &amp;&amp;other){
      the_event = other.the_event;
      it = other.it;
      other.the_event.reset();
    }

    listener(const listener &amp;other) = delete;

    listener &amp; operator=(const listener &amp;other) = delete;

    listener &amp; operator=(listener &amp;&amp;other){
      reset();
      the_event = other.the_event;
      it = other.it;
      other.the_event.reset();
      return *this;
    }

    void observe(event &amp; s,handler f){
      reset();
      the_event = s;
      it = s-&gt;insert(s-&gt;end(),f);
    }

    void reset(){
      if(!the_event.expired()) the_event.lock()-&gt;erase(it);
      the_event.reset();
    }

    ~listener(){ reset(); }
  };

  event():std::shared_ptr&lt;listener_list&gt;(std::make_shared&lt;listener_list&gt;()){ }
  event(const event &amp;) = delete;
  event &amp; operator=(const event &amp;) = delete;

  void notify(Args... args){
    for(auto &amp;f:**this) f(args...);
  }

  listener connect(handler h){
    return listener(*this,h);
  }

};


Example usage:

#include &lt;iostream&gt;

using click_event = event&lt;float,float&gt;;

struct gui_element{
  click_event click;
  void mouse_down(float x,float y){ click.notify(x, y); }
};

int main(int argc, char **argv) {
  gui_element A,B;
  click_event::listener listener_1,listener_2;

  listener_1.observe(A.click,[](float x,float y){ std::cout &lt;&lt; "l1 : A was clicked at " &lt;&lt; x &lt;&lt; ", " &lt;&lt; y &lt;&lt; std::endl; });
  listener_2.observe(B.click,[](float x,float y){ std::cout &lt;&lt; "l2 : B was clicked at " &lt;&lt; x &lt;&lt; ", " &lt;&lt; y &lt;&lt; std::endl; });

  {
  auto temporary_listener = A.click.connect([](float x,float y){ std::cout &lt;&lt; "tmp: A was clicked at " &lt;&lt; x &lt;&lt; ", " &lt;&lt; y &lt;&lt; std::endl; });
  // A has two listeners, B has one listeners
  A.mouse_down(1, 0);
  B.mouse_down(0, 1);
  }

  listener_2 = std::move(listener_1);

  // A has one listener, B has no listeners
  A.mouse_down(2, 0);
  B.mouse_down(0, 2);
}


Output:


l1 : A was clicked at 1, 0
tmp: A was clicked at 1, 0
l2 : B was clicked at 0, 1
l1 : A was clicked at 2, 0



While the usage is exactly how I wanted, I am not sure the implementation is elegant or optimal. Any way how to improve this?
As I said in the comments, your system is pretty close to a system of signals and slots. Congratulations if you never heard of the pattern before, that's an excellent way to implement an the observer design pattern! I still have few notes:


I don't know which compiler you use, but mine won't compile your code unless I include &lt;memory&gt; for std::shared_ptr. I suppose that it may be transitively included from &lt;functional&gt; or &lt;list&gt; in your implementation. Never rely on transitive includes from the standard library and always include the exact header that contains what you need.
Qt, which is the emblematic library when it comes to signals and slots, tends to use past participle for its signas names. For example, instead of click, it would be clicked:

button.clicked.connect(/* whatever */);


It allows to read the line easily as "when button is clicked, do whatever". Also, it makes the object look more like a trigger and less like an action.
From a design point of view, connect being a method taking only one function, I would expect it to add the function to the list, not to return a listener.
You should encapsulate std::shared_ptr&lt;std::list&lt;std::function&lt;void(Args...)&gt;&gt;&gt; instead of inheriting from it. Frankly, you don't want people to expose every method of std::shared_ptr. You don't want people to think of pointers when they want events, right?


The truth is my answer isn't really personal. Since your class obviously looks like a signal class, everything I am saying tends to mean "make your design closer to those of existing signal classes like Boost.Signals2" :/