Jump to page: 1 2
Thread overview
C++ Macro to D mixin template, delegates Please help
Sep 20, 2007
BLS
Sep 20, 2007
Regan Heath
Sep 20, 2007
BLS
Sep 20, 2007
Regan Heath
Sep 20, 2007
BLS
Sep 20, 2007
Regan Heath
Sep 20, 2007
Henning Hasemann
Sep 21, 2007
Regan Heath
Re: C++ Macro to D mixin template, a solution ?
Sep 21, 2007
BLS
Sep 21, 2007
Regan Heath
Sep 21, 2007
BLS
Sep 21, 2007
Regan Heath
Sep 21, 2007
Henning Hasemann
Sep 21, 2007
BLS
Sep 21, 2007
Henning Hasemann
September 20, 2007
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
September 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
September 20, 2007
Regan Heath schrieb:
> 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

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
Bjoern
September 20, 2007
BLS wrote:
> Regan Heath schrieb:
>> 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
> 
> NOOOOOOOOOOoooooooo, Shi* !
> So I guess
> template TFoo(D)
> {
>    alias D delegate() dg
> }
> 
> is also not allowed...

This one is allowed, 'alias' is a declaration.

> 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 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
September 20, 2007
Regan Heath schrieb:
> BLS wrote:
>> Regan Heath schrieb:
>>> 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
>>
>> NOOOOOOOOOOoooooooo, Shi* !
>> So I guess
>> template TFoo(D)
>> {
>>    alias D delegate() dg
>> }
>>
>> is also not allowed...
> 
> This one is allowed, 'alias' is a declaration.
> 
// Means
template ON_WM_CLOSE(D)
{
    alias D delegate() dg;
    if (uID == WM_CLOSE)
    {
        lResult = dg();
        return lResult;
    }
}
// is legal ?


>> 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 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...

>> 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

Well I think I'll ask the Tango folks whether (and how) I can use the Signal/Slot stuff INSTEAD.
Bjoern
September 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".

>>> 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 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...

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 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
> 
> Well I think I'll ask the Tango folks whether (and how) I can use the Signal/Slot stuff INSTEAD.

I might have a peek in there myself, out of interest :)

Regan
September 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
September 21, 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
September 21, 2007
Regan Heath schrieb:
> 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
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. :-)

Bjoern
September 21, 2007
BLS wrote:
> Regan Heath schrieb:
>> Henning Hasemann wrote:

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?

Regan
« First   ‹ Prev
1 2