digitalmars.D.learn - C++ Macro to D mixin template, delegates Please help
- BLS (88/88) Sep 20 2007 Please have a look on my translation.
- Regan Heath (32/40) Sep 20 2007 This seems to be mixing template syntax (using "template") with template...
- BLS (15/64) Sep 20 2007 NOOOOOOOOOOoooooooo, Shi* !
- Regan Heath (6/70) Sep 20 2007 The proposed macro feature should be able to do it.
- BLS (17/93) Sep 20 2007 // Means
- Regan Heath (8/37) Sep 20 2007 Nope. Only the alias line is legal, the rest is illegal because "if" is...
- Henning Hasemann (39/39) Sep 20 2007 Does this help you?
- Regan Heath (6/53) Sep 21 2007 Genius! :)
- BLS (82/138) Sep 21 2007 Indeed smart code. Many Thanks Henning ! But it is not what I need.
- Regan Heath (56/58) Sep 21 2007 I don't understand. What doesn't the code Henning posted do, that you
- BLS (12/82) Sep 21 2007 Probabely, because I am not genius... :-( I 'd better read it twice!
- Regan Heath (21/35) Sep 21 2007 The mixin mixes in a function "newMsgProc" which should overload a base
- Henning Hasemann (27/30) Sep 21 2007 Somehow you can do stuff like this for example:
- BLS (9/47) Sep 21 2007 Just to show you what I am translating :
- Henning Hasemann (8/13) Sep 21 2007 Thanks but as a linux user and for-linux-and-windows coder I dont have
Please have a look on my translation. Problems are 1) porting C++ macros 2) use of delegates within template mixins /* THE C++ Stuff , a fragment class CMsg { public: virtual BOOL NewMsgProc(HWND hWnd, UINT uID, WPARAM wParam, LPARAM lParam,LRESULT lResult) { return FALSE; } }; #define BEGIN_MSG_MAP() \ public: \ virtual BOOL NewMsgProc(HWND hWnd, UINT uID, WPARAM wParam, LPARAM lParam,LRESULT& lResult) \ { \ #define ON_WM_CLOSE(vfunc)\ if (uID == WM_CLOSE) \ { \ lResult =vfunc(); \ return lResult; \ } // and so on ............ class CWin : public CMsg { public: virtual BOOL OnClose() { return TRUE; } BEGIN_MSG_MAP() ON_WM_CLOSE(OnClose) ON_WM_DESTROY(OnDestroy) ON_WM_NCDESTROY(OnNcDestroy) END_MSG_MAP_DEFAULT() } EOF C++ stuff */ THE D port module dgt.win; // All Window's messages will be mapped in this function class CMsg { public: bool NewMsgProc(HWND hWnd, UINT uID, WPARAM wParam, LPARAM lParam,LRESULT lResult) { return false; } } template ON_WM_CLOSE(D) (D delegate() dg) { if (uID == WM_CLOSE) { lResult = dg(); return lResult; } } template ON_MESSAGE_RANGE(M1, M2, D) (M1 MsgF, M2 MsgL, D delegate(...) dg ) { if(uID >= MsgF && uID <= MsgL) { lResult = dg(uID, wParam, lParam); return true; } } // Window class CWin : CMsg { public: bool onClose() { return true; } override bool NewMsgProc(HWND hWnd, UINT uID, WPARAM wParam, LPARAM lParam, ref LRESULT lResult) { mixin ON_WM_CLOSE!(&CWin.OnClose); } } -------------------- Okay, I've ported it as good as I can... the available tutorials are not very helpfull in this case. So please help Bjoern
Sep 20 2007
BLS wrote:template ON_WM_CLOSE(D) (D delegate() dg) { if (uID == WM_CLOSE) { lResult = dg(); return lResult; } }This seems to be mixing template syntax (using "template") with template function syntax (using "(D)(D delegate() dg)". I don't think you want a template function so, rather something like: template ON_WM_CLOSE(alias D) { if (uID == WM_CLOSE) { lResult = D(); return lResult; } } (see the duffs_device example here http://www.digitalmars.com/d/template-mixin.html) However this wont work because a template body can only contain 'declarations' which means; Declaration: typedef Decl alias Decl Decl Decl: StorageClasses Decl BasicType Declarators ; BasicType Declarator FunctionBody AutoDeclaration So, you can put typedefs, aliases, variables and functions in a template, but, what you can't do is put an "if" statement in there. So, templates and mixins in D just can't achieve the same effect as the C/C++ define macro can. The planned/propsed D macro feature however, that should do what you want I reckon. Regan
Sep 20 2007
Regan Heath schrieb:BLS wrote:NOOOOOOOOOOoooooooo, Shi* ! So I guess template TFoo(D) { alias D delegate() dg } is also not allowed... Hell, there should be a way to translate such a simple C++ macro without without having so much trouble!!! I can not imagine that it is impossible. Probabely there exist a workaround. have to look at the Tango Signal/Slot implementation.. Imean they 've managed it. However, thanks Regan Bjoerntemplate ON_WM_CLOSE(D) (D delegate() dg) { if (uID == WM_CLOSE) { lResult = dg(); return lResult; } }This seems to be mixing template syntax (using "template") with template function syntax (using "(D)(D delegate() dg)". I don't think you want a template function so, rather something like: template ON_WM_CLOSE(alias D) { if (uID == WM_CLOSE) { lResult = D(); return lResult; } } (see the duffs_device example here http://www.digitalmars.com/d/template-mixin.html) However this wont work because a template body can only contain 'declarations' which means; Declaration: typedef Decl alias Decl Decl Decl: StorageClasses Decl BasicType Declarators ; BasicType Declarator FunctionBody AutoDeclaration So, you can put typedefs, aliases, variables and functions in a template, but, what you can't do is put an "if" statement in there. So, templates and mixins in D just can't achieve the same effect as the C/C++ define macro can. The planned/propsed D macro feature however, that should do what you want I reckon. Regan
Sep 20 2007
BLS wrote:Regan Heath schrieb:This one is allowed, 'alias' is a declaration.BLS wrote:NOOOOOOOOOOoooooooo, Shi* ! So I guess template TFoo(D) { alias D delegate() dg } is also not allowed...template ON_WM_CLOSE(D) (D delegate() dg) { if (uID == WM_CLOSE) { lResult = dg(); return lResult; } }This seems to be mixing template syntax (using "template") with template function syntax (using "(D)(D delegate() dg)". I don't think you want a template function so, rather something like: template ON_WM_CLOSE(alias D) { if (uID == WM_CLOSE) { lResult = D(); return lResult; } } (see the duffs_device example here http://www.digitalmars.com/d/template-mixin.html) However this wont work because a template body can only contain 'declarations' which means; Declaration: typedef Decl alias Decl Decl Decl: StorageClasses Decl BasicType Declarators ; BasicType Declarator FunctionBody AutoDeclaration So, you can put typedefs, aliases, variables and functions in a template, but, what you can't do is put an "if" statement in there. So, templates and mixins in D just can't achieve the same effect as the C/C++ define macro can. The planned/propsed D macro feature however, that should do what you want I reckon. ReganHell, there should be a way to translate such a simple C++ macro without without having so much trouble!!!The proposed macro feature should be able to do it.I can not imagine that it is impossible. Probabely there exist a workaround. have to look at the Tango Signal/Slot implementation.. Imean they 've managed it.Good idea. I wonder how they're doing it. It's entirely possible that I'm getting something wrong here, I'm no template master. Regan
Sep 20 2007
Regan Heath schrieb:BLS wrote:// Means template ON_WM_CLOSE(D) { alias D delegate() dg; if (uID == WM_CLOSE) { lResult = dg(); return lResult; } } // is legal ?Regan Heath schrieb:This one is allowed, 'alias' is a declaration.BLS wrote:NOOOOOOOOOOoooooooo, Shi* ! So I guess template TFoo(D) { alias D delegate() dg } is also not allowed...template ON_WM_CLOSE(D) (D delegate() dg) { if (uID == WM_CLOSE) { lResult = dg(); return lResult; } }This seems to be mixing template syntax (using "template") with template function syntax (using "(D)(D delegate() dg)". I don't think you want a template function so, rather something like: template ON_WM_CLOSE(alias D) { if (uID == WM_CLOSE) { lResult = D(); return lResult; } } (see the duffs_device example here http://www.digitalmars.com/d/template-mixin.html) However this wont work because a template body can only contain 'declarations' which means; Declaration: typedef Decl alias Decl Decl Decl: StorageClasses Decl BasicType Declarators ; BasicType Declarator FunctionBody AutoDeclaration So, you can put typedefs, aliases, variables and functions in a template, but, what you can't do is put an "if" statement in there. So, templates and mixins in D just can't achieve the same effect as the C/C++ define macro can. The planned/propsed D macro feature however, that should do what you want I reckon. ReganI am not willing to wait another year. My IDE proj. is allready a never ending story, and now I have to create a GUI for it...Hell, there should be a way to translate such a simple C++ macro without without having so much trouble!!!The proposed macro feature should be able to do it.Well I think I'll ask the Tango folks whether (and how) I can use the Signal/Slot stuff INSTEAD. BjoernI can not imagine that it is impossible. Probabely there exist a workaround. have to look at the Tango Signal/Slot implementation.. Imean they 've managed it.Good idea. I wonder how they're doing it. It's entirely possible that I'm getting something wrong here, I'm no template master. Regan
Sep 20 2007
BLS wrote:// Means template ON_WM_CLOSE(D) { alias D delegate() dg; if (uID == WM_CLOSE) { lResult = dg(); return lResult; } } // is legal ?Nope. Only the alias line is legal, the rest is illegal because "if" is not a "declaration", it is a "statement".I'm hoping it arrives faster than that, but I guess you can't really bank on it. Walters last foray into the forums was about 'const' so I expect he's working on that as a top priority, but I could be wrong.I am not willing to wait another year. My IDE proj. is allready a never ending story, and now I have to create a GUI for it...Hell, there should be a way to translate such a simple C++ macro without without having so much trouble!!!The proposed macro feature should be able to do it.I might have a peek in there myself, out of interest :) ReganWell I think I'll ask the Tango folks whether (and how) I can use the Signal/Slot stuff INSTEAD.I can not imagine that it is impossible. Probabely there exist a workaround. have to look at the Tango Signal/Slot implementation.. Imean they 've managed it.Good idea. I wonder how they're doing it. It's entirely possible that I'm getting something wrong here, I'm no template master. Regan
Sep 20 2007
Does this help you? import std.stdio; template MessageMap(Mappings ...) { void newMsgProc(uint uID) { foreach(mapping; Mappings) { if(mapping.matches(uID)) mapping.executeAction(); } } } struct OnClose(alias fn) { alias fn executeAction; static bool matches(uint uid) { return uid == 5; } } struct OnRange(uint a, uint b, alias fn) { alias fn executeAction; static bool matches(uint uid) { return uid >= a && uid <= b; } } class Foo { void foo() { writefln("foo called"); } void bar() { writefln("bar called"); } mixin MessageMap!( OnClose!(foo), OnRange!(1, 3, bar) ); } void main() { auto f = new Foo; f.newMsgProc(5); f.newMsgProc(2); } -- GPG Public Key: http://keyserver.ganneff.de:11371/pks/lookup?op=get&search=0xDDD6D36D41911851 Fingerprint: 344F 4072 F038 BB9E B35D E6AB DDD6 D36D 4191 1851
Sep 20 2007
Henning Hasemann wrote:Does this help you? import std.stdio; template MessageMap(Mappings ...) { void newMsgProc(uint uID) { foreach(mapping; Mappings) { if(mapping.matches(uID)) mapping.executeAction(); } } } struct OnClose(alias fn) { alias fn executeAction; static bool matches(uint uid) { return uid == 5; } } struct OnRange(uint a, uint b, alias fn) { alias fn executeAction; static bool matches(uint uid) { return uid >= a && uid <= b; } } class Foo { void foo() { writefln("foo called"); } void bar() { writefln("bar called"); } mixin MessageMap!( OnClose!(foo), OnRange!(1, 3, bar) ); } void main() { auto f = new Foo; f.newMsgProc(5); f.newMsgProc(2); }Genius! :) See BLS I told you someone else would come up with something. Sadly my mind doesn't operate in a very templatey fashion .. yet .. I need more practice. Regan
Sep 21 2007
Regan Heath schrieb:Henning Hasemann wrote:Indeed smart code. Many Thanks Henning ! But it is not what I need. I really hope that I can use mixins (NOT template mixins) let me show you : //A C++ fragment from the MSG_MAP macro #define ON_WM_CLOSE(vfunc)\ if (uID == WM_CLOSE) \ { \ lResult =vfunc(); \ return lResult; \ } // becomes in D template ON_WM_CLOSE(char[] vfunc) { const char[] ON_WM_CLOSE = "if (uID == WM_CLOSE) { lResult = " ~ vfunc ~ "; return lResult; }"; } //use case : mixin(ON_WM_CLOSE!("onClose()")) Let's have a look at : 1) The original C++ class class CWin : public CMsg { public: virtual BOOL OnClose() { return TRUE; } BEGIN_MSG_MAP() ON_WM_CLOSE(OnClose) END_MSG_MAP_DEFAULT() ] -------------------------------------------- which expands to class CWin : public CMsg { public: virtual BOOL OnClose() { return TRUE; } // BEGIN_MSG_MAP virtual BOOL NewMsgProc(HWND hWnd, UINT uID, WPARAM wParam, LPARAM lParam,LRESULT& lResult) { //ON_WM_CLOSE if (uID == WM_CLOSE) { lResult =onClose(); // CALL onClose !! AND SET lResult return lResult; } //END_MSG_MAP_DEFAULT() // whatever } 2) The D code class CWin : CMsg { public: bool onClose() { return true; } // C++ BEGIN_MSG_MAP() becomes override bool NewMsgProc(HWND hWnd, UINT uID, WPARAM wParam, LPARAM lParam, ref LRESULT lResult) { mixin(ON_WM_CLOSE!("onClose()")) //C++ ON_WM_CLOSE(OnClose) } } --------------------------------------------------------------------------- //Again the D ON_WM_CLOSE mixin template ON_WM_CLOSE(char[] vfunc) { const char[] ON_WM_CLOSE = "if (uID == WM_CLOSE) { lResult = " ~ vfunc ~ "; return lResult; }"; } Comments ? Is it legal to use mixins this way ? http://www.digitalmars.com/d/mixin.html It seems that C++ macros are just text substitutions. I was really confused about the "lResult = vFunc() stuff within the ON_WM_CLOSE #define. Dunno much about C++ but the more I learn the more I hate it. :-) BjoernDoes this help you? import std.stdio; template MessageMap(Mappings ...) { void newMsgProc(uint uID) { foreach(mapping; Mappings) { if(mapping.matches(uID)) mapping.executeAction(); } } } struct OnClose(alias fn) { alias fn executeAction; static bool matches(uint uid) { return uid == 5; } } struct OnRange(uint a, uint b, alias fn) { alias fn executeAction; static bool matches(uint uid) { return uid >= a && uid <= b; } } class Foo { void foo() { writefln("foo called"); } void bar() { writefln("bar called"); } mixin MessageMap!( OnClose!(foo), OnRange!(1, 3, bar) ); } void main() { auto f = new Foo; f.newMsgProc(5); f.newMsgProc(2); }Genius! :) See BLS I told you someone else would come up with something. Sadly my mind doesn't operate in a very templatey fashion .. yet .. I need more practice. Regan
Sep 21 2007
BLS wrote:Regan Heath schrieb:I don't understand. What doesn't the code Henning posted do, that you need it to do?? class Foo { void foo() { writefln("foo called"); } void bar() { writefln("bar called"); } mixin MessageMap!( OnClose!(foo), OnRange!(1, 3, bar) ); } expands to: class Foo { void foo() { writefln("foo called"); } void bar() { writefln("bar called"); } void newMsgProc(uint uID) { //expands just like "BEGIN_MSG_MAP" foreach(mapping; Mappings) { //loops 2x if(mapping.matches(uID)) //just like "if (uID == WM_CLOSE)" mapping.executeAction(); //just like "vfunc();" } } } Change MessageMap to expand to the function fignature you want, i.e. template MessageMap(Mappings ...) { override BOOL NewMsgProc(HWND hWnd, UINT uID, WPARAM wParam, LPARAM lParam, ref LRESULT lResult) { foreach(mapping; Mappings) { if(mapping.matches(uID)) mapping.executeAction(); } } } Change MessageMap to return the result of the mapping.executeAction just like "return lResult;" in the original C++. template MessageMap(Mappings ...) { override BOOL NewMsgProc(HWND hWnd, UINT uID, WPARAM wParam, LPARAM lParam, ref LRESULT lResult) { foreach(mapping; Mappings) { if(mapping.matches(uID)) { lResult = mapping.executeAction(); return cast(BOOL)lResult; } } } } I think it's ok to use mixins as you're desribing, but why do you need to do it that way? ReganHenning Hasemann wrote:
Sep 21 2007
Regan Heath schrieb:BLS wrote:Probabely, because I am not genius... :-( I 'd better read it twice! Just one question : It seems that you use template overloading, or do I miss something. In other words : Can I use template overloading like function overloading ? Many thanks for your efforts, Regan and Henning ! BjoernRegan Heath schrieb:I don't understand. What doesn't the code Henning posted do, that you need it to do??Henning Hasemann wrote:class Foo { void foo() { writefln("foo called"); } void bar() { writefln("bar called"); } mixin MessageMap!( OnClose!(foo), OnRange!(1, 3, bar) ); } expands to: class Foo { void foo() { writefln("foo called"); } void bar() { writefln("bar called"); } void newMsgProc(uint uID) { //expands just like "BEGIN_MSG_MAP" foreach(mapping; Mappings) { //loops 2x if(mapping.matches(uID)) //just like "if (uID == WM_CLOSE)" mapping.executeAction(); //just like "vfunc();" } } } Change MessageMap to expand to the function fignature you want, i.e. template MessageMap(Mappings ...) { override BOOL NewMsgProc(HWND hWnd, UINT uID, WPARAM wParam, LPARAM lParam, ref LRESULT lResult) { foreach(mapping; Mappings) { if(mapping.matches(uID)) mapping.executeAction(); } } } Change MessageMap to return the result of the mapping.executeAction just like "return lResult;" in the original C++. template MessageMap(Mappings ...) { override BOOL NewMsgProc(HWND hWnd, UINT uID, WPARAM wParam, LPARAM lParam, ref LRESULT lResult) { foreach(mapping; Mappings) { if(mapping.matches(uID)) { lResult = mapping.executeAction(); return cast(BOOL)lResult; } } } } I think it's ok to use mixins as you're desribing, but why do you need to do it that way? ReganProbabely, because I am not genius... :-( I 'd better read it twice! Just one question : It seems that you use template overloading, or do I miss something. In other words is template overloading legal ? Many thanks for your efforts, Regan and Henning ! Bjoern
Sep 21 2007
BLS wrote:Regan Heath schrieb:Join the club ;)BLS wrote:Probabely, because I am not genius... :-( I 'd better read it twice!Regan Heath schrieb:I don't understand. What doesn't the code Henning posted do, that you need it to do??Henning Hasemann wrote:Just one question : It seems that you use template overloading, or do I miss something.The mixin mixes in a function "newMsgProc" which should overload a base class function of the same signature (whether mixed in also or typed). I think this works, but I am not 100% certain. The docs do say: "Templates cannot be used to add non-static members or functions to classes" on the templates page, but I'm not sure if that applies to "template mixins" too, or what.In other words : Can I use template overloading like function overloading ?I think so, however you can't mix template function and function overloading, i.e. class Foo { void foo(T)(T arg) { } void foo(float arg) { } } But Walter plans to make this work I believe. Regan
Sep 21 2007
Thanks for all the compliments :)Just one question : It seems that you use template overloading, or do I miss something. In other words : Can I use template overloading like function overloading ?Somehow you can do stuff like this for example: template Foo(int n, T) { // some stuff } template Foo(T) { // something else } You can even define templates differently for different types, but thats called "specialisation" not overloading. But I dont use such a thing here. What I do is defining a few templated structs and the structs (not instances of them, the actual type!) are given to MessageMap which calls the static functions. So technically, OnClose!(foo) and OnRange!(1, 3, bar) are *types* that contain aliases (think of compile time references) to the methods you want to call. The "mixin MessageMap!(...)" simply adds a new method to your class. Note that because it is run over types, the "foreach(mapping; Mappings) { .. }" is done at compile time, ie its body is repeated for every type (I called them Mapping's here), so all runtime overhead you have are the ifs that evaluate to false. If you have further questions, dont hesitate to ask :) Henning -- GPG Public Key: http://keyserver.ganneff.de:11371/pks/lookup?op=get&search=0xDDD6D36D41911851 Fingerprint: 344F 4072 F038 BB9E B35D E6AB DDD6 D36D 4191 1851
Sep 21 2007
Henning Hasemann schrieb:Thanks for all the compliments :)I am afraid that will happen :-)Just one question : It seems that you use template overloading, or do I miss something. In other words : Can I use template overloading like function overloading ?Somehow you can do stuff like this for example: template Foo(int n, T) { // some stuff } template Foo(T) { // something else } You can even define templates differently for different types, but thats called "specialisation" not overloading. But I dont use such a thing here. What I do is defining a few templated structs and the structs (not instances of them, the actual type!) are given to MessageMap which calls the static functions. So technically, OnClose!(foo) and OnRange!(1, 3, bar) are *types* that contain aliases (think of compile time references) to the methods you want to call. The "mixin MessageMap!(...)" simply adds a new method to your class. Note that because it is run over types, the "foreach(mapping; Mappings) { .. }" is done at compile time, ie its body is repeated for every type (I called them Mapping's here), so all runtime overhead you have are the ifs that evaluate to false. If you have further questions, dont hesitate to ask :)HenningJust to show you what I am translating : http://www.beyondata.com/pwc.html A really smart GUI. Download if you like the Pretty WinApi Class, it is a small one. (I need as GUI toolkit for my IDE project) However, thanks to your and Regan's help I am ready to give it a go. Many thanks ! Bjoern
Sep 21 2007
Just to show you what I am translating : http://www.beyondata.com/pwc.html A really smart GUI. Download if you like the Pretty WinApi Class, it is a small one. (I need as GUI toolkit for my IDE project)Thanks but as a linux user and for-linux-and-windows coder I dont have a real use for a win-only gui lib... I'd be more happy about a good gtk wrapper with active development. Henning -- GPG Public Key: http://keyserver.ganneff.de:11371/pks/lookup?op=get&search=0xDDD6D36D41911851 Fingerprint: 344F 4072 F038 BB9E B35D E6AB DDD6 D36D 4191 1851
Sep 21 2007