www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - variadic mixin templates and other stuff

reply Martin Drasar <drasar ics.muni.cz> writes:
Hi,

I am migrating a C++ project to D and I have hit a roadblock that I hope
you might help me with.

My code is heavily inspired by the COM architecture, so I have naturally
take a look at std/c/windows/com.d, just to find out that it does not
contain all I need.

In the C++ code I have several interfaces and a class. The class
inherits from these interfaces, exposes some of them and it is possible
to get one interface from another using the QueryInterface function by
supplying correct GUID:

class C : IA, IB, IC
{
  EXPOSE_INTERFACE(IA, IC);
  ...
}

where EXPOSE_INTERFACE is macro that expands to something like this:

void QueryInterface (IComponent** comp, GUID* guid)
{
  ...
  if (guid == IAGuid) *comp = ...some casting
  if (guid == IBGuid) *comp = ...some casting
  ...
}

So I was thinking that in D I could use mixin templates with variadic
arguments, so I tried something like that:

string interfaceGuid(string ifaceName)
{
  return ifaceName ~ "Guid";
}

mixin template EXPOSE_INTERFACE(string ifaceName)
{
  if (mixin(interfaceGuid(ifaceName)) == guid) { ... some casting }
}

mixin template EXPOSE_INTERFACES(T...)(T args)
{
  void QueryInterface(ref IComponent comp, string guid)
  {
    foreach (arg; args)
    {
      mixin EXPOSE_INTERFACE!arg;
    }
  }
}

But I got this:

component.d(8): Declaration expected, not 'if'
component.d(15): no identifier for declarator args
component.d(15): semicolon expected, not ')'
component.d(15): Declaration expected, not ')'
component.d(19): unrecognized declaration

Then I got confused and realized that my D is as sharp as is my German -
studied it for some time, but still has a problem to order a bread in a
store...

My questions are following:
- can mixin templates be used this way?
- why are they complaining?
- is there a better way to do this other than reproducing C macros?

Thanks,
Martin
Apr 20 2012
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 04/20/2012 03:23 PM, Martin Drasar wrote:
 Hi,

 I am migrating a C++ project to D and I have hit a roadblock that I hope
 you might help me with.

 My code is heavily inspired by the COM architecture, so I have naturally
 take a look at std/c/windows/com.d, just to find out that it does not
 contain all I need.

 In the C++ code I have several interfaces and a class. The class
 inherits from these interfaces, exposes some of them and it is possible
 to get one interface from another using the QueryInterface function by
 supplying correct GUID:

 class C : IA, IB, IC
 {
    EXPOSE_INTERFACE(IA, IC);
    ...
 }

 where EXPOSE_INTERFACE is macro that expands to something like this:

 void QueryInterface (IComponent** comp, GUID* guid)
 {
    ...
    if (guid == IAGuid) *comp = ...some casting
    if (guid == IBGuid) *comp = ...some casting
    ...
 }

 So I was thinking that in D I could use mixin templates with variadic
 arguments, so I tried something like that:

 string interfaceGuid(string ifaceName)
 {
    return ifaceName ~ "Guid";
 }

 mixin template EXPOSE_INTERFACE(string ifaceName)
 {
    if (mixin(interfaceGuid(ifaceName)) == guid) { ... some casting }
 }

 mixin template EXPOSE_INTERFACES(T...)(T args)
 {
    void QueryInterface(ref IComponent comp, string guid)
    {
      foreach (arg; args)
      {
        mixin EXPOSE_INTERFACE!arg;
      }
    }
 }

 But I got this:

 component.d(8): Declaration expected, not 'if'
 component.d(15): no identifier for declarator args
 component.d(15): semicolon expected, not ')'
 component.d(15): Declaration expected, not ')'
 component.d(19): unrecognized declaration

 Then I got confused and realized that my D is as sharp as is my German -
 studied it for some time, but still has a problem to order a bread in a
 store...

 My questions are following:
 - can mixin templates be used this way?
They can only mixin declarations.
 - why are they complaining?
Because if is a statement and not a declaration.
 - is there a better way to do this other than reproducing C macros?
Inline EXPOSE_INTERFACE into EXPOSE_INTERFACES and it'll work.
Apr 20 2012
parent reply Martin Drasar <drasar ics.muni.cz> writes:
On 20.4.2012 16:09, Timon Gehr wrote:

Thanks Timon for the answer.

 My questions are following:
 - can mixin templates be used this way?
They can only mixin declarations.
 - why are they complaining?
Because if is a statement and not a declaration.
Ok.
 - is there a better way to do this other than reproducing C macros?
Inline EXPOSE_INTERFACE into EXPOSE_INTERFACES and it'll work.
I tried but it still refuses to compile: string interfaceGuid(string ifaceName) { return ifaceName ~ "Guid"; } mixin template EXPOSE_INTERFACES(T...)(T args) { void QueryInterface(ref IComponent comp, string guid) { foreach (arg; args) { if (mixin(interfaceGuid(arg)) == guid) {} } } } component.d(6): members of template declaration expected component.d(6): Declaration expected, not '(' component.d(10): no identifier for declarator args component.d(10): semicolon expected, not ')' component.d(10): Declaration expected, not ')' I am compiling it with dmd v2.058. Martin
Apr 20 2012
parent reply "John Chapman" <johnch_atms hotmail.com> writes:
On Friday, 20 April 2012 at 14:57:03 UTC, Martin Drasar wrote:
 On 20.4.2012 16:09, Timon Gehr wrote:

 I tried but it still refuses to compile:

 string interfaceGuid(string ifaceName)
 {
   return ifaceName ~ "Guid";
 }

 mixin template EXPOSE_INTERFACES(T...)(T args)
Try this: mixin template EXPOSE_INTERFACES(T...)
 {
   void QueryInterface(ref IComponent comp, string guid)
   {
     foreach (arg; args)
and this: foreach (arg; T)
     {
       if (mixin(interfaceGuid(arg)) == guid) {}
     }
   }
 }

 component.d(6): members of template declaration expected
 component.d(6): Declaration expected, not '('
 component.d(10): no identifier for declarator args
 component.d(10): semicolon expected, not ')'
 component.d(10): Declaration expected, not ')'

 I am compiling it with dmd v2.058.

 Martin
John
Apr 20 2012
parent Martin Drasar <drasar ics.muni.cz> writes:
On 20.4.2012 19:00, John Chapman wrote:
 On Friday, 20 April 2012 at 14:57:03 UTC, Martin Drasar wrote:
 On 20.4.2012 16:09, Timon Gehr wrote:

 I tried but it still refuses to compile:

 string interfaceGuid(string ifaceName)
 {
   return ifaceName ~ "Guid";
 }

 mixin template EXPOSE_INTERFACES(T...)(T args)
Try this: mixin template EXPOSE_INTERFACES(T...)
 {
   void QueryInterface(ref IComponent comp, string guid)
   {
     foreach (arg; args)
and this: foreach (arg; T)
     {
       if (mixin(interfaceGuid(arg)) == guid) {}
     }
   }
 }
Hi John, thanks very much. That did the trick. I am still wondering - why my previous code did not work? This is the syntax I have adopted from variadic functions in TDPL. Why does it work with functions and not mixin templates? Thanks, Martin
Apr 21 2012