Metaprogramming work around

Kenji Hara k.hara.pg at gmail.com
Tue Apr 17 03:29:54 PDT 2012


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


More information about the Digitalmars-d-learn mailing list