Metaprogramming work around
"Erèbe"
erebe at erebe.eu
Tue Apr 17 05:04:42 PDT 2012
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 ?
More information about the Digitalmars-d-learn
mailing list