www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - YAP: variadic templates via arrays and static foreach

reply Serg Kovrov <kovrov no.spam> writes:
Hi All,
Sorry for bothering, but another proposal...
Idea is to use some sort of 'static foreach' for array parameters.

 struct MSG
 {
   int msg;
   int function() hdlr;
 }
 
 template msgHdlr(MSG[] T)
 {
   int handleMessage(int msg, int cmd)
   {
     switch (msg)
     {
       case WM_MOVE:
         onMove();
         break;
       static foreach(MSG m; T)  //  <-- here
       {
         case mixin!(m.msg):     //  <-- here
           mixin!(m.hdlr)();     //  <-- here
           break;
       }
       default:
     }
   }
 }
 
 static MSG[] messages
 [
   { WM_CREATE, &onCreate },
   { WM_CLOSE,  &onClose },
 ]
 
 class MyWindow
 {
   mixin msgHdlr!(messages) //  <-- and finally here
 }

This code should result same as followed:
 class MyWindow
 {
   int handleMessage(int msg, int cmd)
   {
     switch (msg)
     {
       case WM_MOVE:
         onMove();
         break;
       case WM_CREATE:
         onCreate();
         break;
       case WM_CLOSE:
         onClose();
         break;
       default:
     }
   }
 }

Inspired by message map macros in WTL/MFC -- serg.
Aug 09 2006
parent reply Derek Parnell <derek nomail.afraid.org> writes:
On Thu, 10 Aug 2006 02:37:44 +0300, Serg Kovrov wrote:

 Hi All,
 Sorry for bothering, but another proposal...
 Idea is to use some sort of 'static foreach' for array parameters.

Let me introduce you to associative arrays ... //------------- import std.c.windows.windows; import std.stdio; alias int function() hdlr; hdlr[int] Handlers; // -- AA of handlers. static this() { // Initialize the AA Handlers[WM_MOVE] = &onMove; Handlers[WM_CREATE] = &onCreate; Handlers[WM_CLOSE] = &onClose; } class MyWindow { int handleMessage(int msg, int cmd) { int res; hdlr* h; if ((h = (msg in Handlers)) !is null) res = (*h)(); return res; } } // Example functions. int onMove() { return 1; } int onCreate() { return 2; } int onClose() { return 3; } void main() { auto w = new MyWindow; std.stdio.writefln("%s %s", WM_MOVE, w.handleMessage(WM_MOVE, 0)); std.stdio.writefln("%s %s", WM_CREATE, w.handleMessage(WM_CREATE, 0)); std.stdio.writefln("%s %s", WM_CLOSE, w.handleMessage(WM_CLOSE, 0)); } //----------- -- Derek (skype: derek.j.parnell) Melbourne, Australia "Down with mediocrity!" 10/08/2006 11:05:38 AM
Aug 09 2006
parent reply Serg Kovrov <kovrov no.spam> writes:
* Derek Parnell:
 Let me introduce you to associative arrays ...
 
 //-------------
 import std.c.windows.windows;
 import std.stdio;
 
 alias int function() hdlr;
 hdlr[int] Handlers; // -- AA of handlers.
 
 static this()
 {
     // Initialize the AA
     Handlers[WM_MOVE] = &onMove;
     Handlers[WM_CREATE] = &onCreate;
     Handlers[WM_CLOSE] = &onClose;
 }

Thanks Derek, sure it is nice solution for this case. I use this exact technique for xml parsing rules definition. And it would be even nicer to have static initialization of static associative arrays... Hope Walter get tired of regular requests for it and will implement it eventually =) I wonder if static associative arrays lookups works as fast as switch statement? But original idea was to mixin some cases to switch in a sophisticated (possibly library) function. Sure my example were simple, but thats for not overflood message with example code.
Aug 10 2006
parent BCS <BCS pathlink.com> writes:
Serg Kovrov wrote:
 * Derek Parnell:
 
 Let me introduce you to associative arrays ...

 //-------------
 import std.c.windows.windows;
 import std.stdio;

 alias int function() hdlr;
 hdlr[int] Handlers; // -- AA of handlers.

 static this()
 {
     // Initialize the AA
     Handlers[WM_MOVE] = &onMove;
     Handlers[WM_CREATE] = &onCreate;
     Handlers[WM_CLOSE] = &onClose;
 }

Thanks Derek, sure it is nice solution for this case. I use this exact technique for xml parsing rules definition. And it would be even nicer to have static initialization of static associative arrays... Hope Walter get tired of regular requests for it and will implement it eventually =) I wonder if static associative arrays lookups works as fast as switch statement? But original idea was to mixin some cases to switch in a sophisticated (possibly library) function. Sure my example were simple, but thats for not overflood message with example code.

This sounds a lot like an idea I posted about ~1 year ago, the "witheach" statement. (it never went anywhere) http://www.digitalmars.com/d/archives/digitalmars/D/32232.html The idea is that you provide a syntacticly valid block of code and a set of "things". The compiler unrolls the construct by takes each "thing" in turn and instances the code with that "thing" aliased in as something. static ifs are processed after this unrolling so each instance can be handled differently depending on what the thing is. The set that it operates on could be an enumeration, a struct or class type, a list of function (of different types), or whatever. The kind of usage it could be put to would include your original problem and things like a byte order swapper for structs #struct fig #{ # char c; # byte b; # short s; # int i; # long l; # real r; # fig* f; #} # #void ByteSwap(inout fig f) #{ # witheach(a;fig) // instance with "a" aliased as each element # { # static if(is(*f.a)) # { # if(null !is f.a) # ByteSwap(*f.a); # } # else # ByteSwap(f.a); # // calls correct ByteSwap for each iteration # // all type resolution is done at compile time # } #} Adding more elements to fig will cause the witheach to add more code. (BTW I don't think I'm using the same syntax here as I suggested originally).
Aug 10 2006