On Tuesday, 17 April 2012 at 10:29:56 UTC, Kenji Hara wrote:
On Tuesday, 17 April 2012 at 08:28:45 UTC, Erèbe wrote:
Hi,

I'm working on some metaprogramming code which implement a Factory and generate an enum from a list of string.

So here my questions :

1) The documentation say mixin templates could take as TemplateParameterList a "TemplateParameter , TemplateParameterList" but all my tried to instaciate this template failed lamentably.

mixin template Foo(T, R...)
{

  anotherTemplate!(T);
  Foo!(R);

}

mixin Foo!( string, string, string);

Is something wrong with variadic template and mixin, do i miss something ?


2) Below some code I writed and I wanted to know if you have some advice to improve it (Right maner to do it, TypeChecking, Safety, ...) <- variaidc arguments


The code is working is purpose is to create an enum of commands and to create a factory which returns me the command associated to a string.

Thanks !

===========================Code============================================
import std.stdio;
import std.traits;
import std.conv;


//Use to create the enums of every commands
mixin template enumGenerator( T... )
{

   template generate( T... )
   {
enum string value = T[0] ~ ", " ~ generate!( T[2..$] ).value;
   }

   template generate() { enum string value = "UNKNOW"; }


   //Here the creation of the enum
   mixin("enum Command { " ~ generate!(T).value ~ "};");

}

//Generate a function which return a command in regard of a string
mixin template factoryGenerator( T... )
{
   template generate( T... )
   {
       enum string value = "if( cmd == \"" ~ T[1] ~ "\")"
                               ~ "return Command." ~ T[0] ~ ";"
                           ~ "else "
                               ~ generate!(T[2..$]).value;
   }

template generate() { enum string value = "return Command.UNKNOW;"; }

   //The function in question
   auto CommandFactory( string cmd )
   {
           mixin( generate!(T).value );
   }

}


mixin template IrcCommands( T... )
{

  mixin enumGenerator!( T );
  mixin factoryGenerator!( T );

}


void main()
{

                      /*Command*/     /*String associated*/
  mixin IrcCommands!( "Connected",    "001",
                      "NicknameUsed", "433",
                      "Message",      "PRIVMSG",
                      "UserLeaved",   "PART",
                      "UserJoined",   "JOIN",
                      "UserQuit",     "QUIT"

"UserQuit", "QUIT", // lack of comma

                      "Ping",         "PING" );

  writefln( to!string(CommandFactory("001")) );


}

You can debug templates with adding static assertions in some where, like:

mixin template enumGenerator( T... )
{
    template generate( T... )
    {
static assert(T.length%2==0 && is(typeof(T[0]) : string)); // check enum string value = T[0] ~ ", " ~ generate!( T[2..$] ).value;
    }
    //[snip]
}

mixin template factoryGenerator( T... )
{
    template generate( T... )
    {
static assert(T.length%2==0 && is(typeof(T[1]) : string)); // check
        enum string value = "if( cmd == \"" ~ T[1] ~ "\")"
                                ~ "return Command." ~ T[0] ~ ";"
                            ~ "else "
                                ~ generate!(T[2..$]).value;
    }
    //[snip]
}

Bye.

Kenji Hara

Thanks for the comma !

The issue with static assert (in my case) is that the compiler blow you a full page of "template's instatiation error" before the message of your assert. Ok not even a page of the size of c++ template error, but that lead to your message be less noticeable.
While browsering the standard librairy I found this :

static if ( expression )
     //put your code here
else
  assert(false, "your message");

With this, the compiler print just one line, "your message". That pretty neat and readable enough for me :)

Stick in the magic pragma(msg, value); in here you won't regret it ;) Another important thing to note here is that you should really reconsider using plain if/else if it's a production code not some toy to learn meta programming. At very least try to generate switch over strings but I don't think any D compiler optimizes it. (but it should in future) Real world options are binary search on string table or even better built-in hash table.

Thanks for pragma, it's awesome !

You guessed right, this code is just for the sake of learning some D meta programming. But I will try with an built-in hash table.



There is something I still don't understand :

mixin template Foo( T... )
{
//Code here
}

mixin Foo!( "Hello", "Word" ); <---- Good

--------------------------------------------

mixin template Foo( A, T... )
{
//code here
}

mixin Foo!( "Hello", "Word" ); <--- Fail !
mixin Foo!( string, "Word" ); <---- Good
--------------------------------------------

mixin template Foo( alias A, T... )
{
//code here
}

mixin Foo!( "Hello", "world" ); <--- Good
mixin Foo!( string, "world" ); <--- Fail !

---------------------------------------------

Is there someone to enlight me about this behavior ?


Reply via email to