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.