On Tuesday, 26 January 2016 at 19:22:58 UTC, Ali Çehreli wrote:
On 01/26/2016 10:41 AM, tcak wrote:
> I need/want this class to be able to bind
> a function, a method, or a shared method. From the
perspective of class
> design, there shouldn't be any
> difference. Its purpose is to let know about the event, not
to care
> about how the event
> handler is designed.

If I understand the problem correctly, an interface can define the interface and a templated class can provide the differences:

import std.stdio;
import std.algorithm;

interface Event {
    void start();
    void stop();
    void itemAdded( size_t itemIndex );
}

class ConcreteEvent(alias onStart, alias onStop, alias onItemAdded) : Event {
    void start() {
        onStart();
    }

    void stop() {
        onStop();
    }

    void itemAdded(size_t itemIndex) {
        itemAdded(itemIndex);
    }
}

void fooStart() {
}

void fooStop() {
}

void fooItemAdded(size_t itemIndex) {
}

void bar(size_t itemIndex) {
}

void main() {
    Event[] events;
events ~= new ConcreteEvent!(fooStart, fooStop, fooItemAdded);

    struct S {
        void memberFunction() {
        }
    }
    auto s = S();

auto memberClosure(ref S s) {On 01/26/2016 10:41 AM, tcak wrote:
> I need/want this class to be able to bind
> a function, a method, or a shared method. From the
perspective of class
> design, there shouldn't be any
> difference. Its purpose is to let know about the event, not
to care
> about how the event
> handler is designed.

If I understand the problem correctly, an interface can define the interface and a templated class can provide differences:

import std.stdio;
import std.algorithm;

interface Event {
    void start();
    void stop();
    void itemAdded( size_t itemIndex );
}

class ConcreteEvent(alias onStart, alias onStop, alias onItemAdded) : Event {
    void start() {
        onStart();
    }

    void stop() {
        onStop();
    }

    void itemAdded(size_t itemIndex) {
        itemAdded(itemIndex);
    }
}

void fooStart() {
}

void fooStop() {
}

void fooItemAdded(size_t itemIndex) {
}

void bar(size_t itemIndex) {
}

void main() {
    Event[] events;
events ~= new ConcreteEvent!(fooStart, fooStop, fooItemAdded);

    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

        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. 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 )();

        gen1.bark();
        gen2.bark();
}


Error is given on "auto gen2 = ..." in main function due to passing method. I guess because it is runtime normal compile time information.

I was looking for something like to be defined in the class Generator:

public DelegateOnStart eventOnStart;

So I could set eventOnStart as either function pointer, method pointer, or shared method pointer. To be able to support three of them, for every event, I need to define another variable, another alias, and while calling, check whichever variable (delegate pointer) is set, and call that one. I hope I am making it clear why it turns into mess.

Reply via email to