Defining event handlers for function, method, or shared method

Ali Çehreli via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Tue Jan 26 11:57:11 PST 2016


On 01/26/2016 11:42 AM, tcak wrote:

 >>     struct S {
 >>         void memberFunction() {
 >>         }
 >>     }
 >>     auto s = S();
 >>
 >>     auto memberClosure(ref S s) {
 >>         return () => s.memberFunction();
 >>     }
 >>
 >>     events ~= new ConcreteEvent!(() => memberClosure(s),
 >>                                  () => writeln("stop"),
 >>                                  bar);
 >>
 >>     events.each!(e => e.stop);
 >> }
 >>
 >> Ali

 > Hmm. Your example works fine for functions, but I can't pass a method
 > instead of function as alias.

That's why I used a closure in the example.

 > Check my example:
 >
 >
 > import std.socket;
 >
 > class EventClass{
 >      public void eventHandlerMethod(){
 >          writeln("Barking from method");
 >      }
 > }
 >
 > class Generator(alias eventHandler){
 >      public void bark(){
 >          eventHandler();
 >      }
 > }
 >
 > public void eventHandlerFunc(){
 >      writeln("Barking from function");
 > }
 >
 > void main(){
 >      auto events = new EventClass;
 >
 >      auto gen1 = new Generator!( eventHandlerFunc )();
 >      auto gen2 = new Generator!( events.eventHandlerMethod )();

As far as I know, just the member function name cannot be used that way. 
The problem boils down to how to create a type (or an alias) that will 
call a specific member function of a given object.

One way is to have a dedicated type that always call foo():

import std.stdio;

class C {
     void foo() {
         writeln("foo called");
     }
}

class FooCaller {
     C c;

     this (C c) {
         this.c = c;
     }

     void call() {
         c.foo();    // hard-coded to call foo()
     }
}

void main() {
     auto f = new FooCaller(new C());
     f.call();
}

The following one creates a lambda (closure in this case?) that allows 
the user to pick which member function to call. Admittedly, 
CallableCaller() is not really needed in this example but it 
demonstrates how "a member function call on a specific object" can be 
passed as an alias template parameter:

import std.stdio;

class C {
     void foo() {
         writeln("foo called");
     }
}

class CallableCaller(alias closure) {
     void call() {
         closure();
     }
}

void main() {
     auto c = new C();
     auto f = new CallableCaller!(() => c.foo());
     f.call();
}

Ali



More information about the Digitalmars-d-learn mailing list