how to handle void arguments in generic programming ?

Timon Gehr timon.gehr at gmx.ch
Mon Nov 11 05:32:16 PST 2013


On 11/11/2013 02:06 PM, Timon Gehr wrote:
>
> Or, if you care about evaluation order and locking stdout:

This was a little too quick. It does not work too well since if the last 
parameter is of type void, the newline is emitted before the trailing 
arguments of type void are evaluated, which may not be exactly what you 
wanted.

The following should work, however DMD does not properly support the 
(exp,Seq!()) construct, so it won't compile in this case:


alias Seq(T...)=T;
void writelnIfNonVoid(T...)(lazy T a){
     import std.range, std.algorithm, std.conv;
     mixin({
         string[] 
indices=iota(a.length).map!(i=>"a["~to!string(i)~"]").array~"Seq!()";
         string r;
         foreach(i,t;T){
             if(is(t==void))
                 indices[i+1]="("~indices[i]~","~indices[i+1]~")";
             else r~=indices[i]~",";
         }
         if(r.length) return "writeln("~r~indices[$-1]~");";
         return indices[$-1]!="Seq!()"?indices[$-1]~";":"";
     }());
}

This could be worked around as follows, but then you might get more 
postblit invocations than in the previous version:

import std.stdio;

void main(){
     writelnIfNonVoid("123",writeln("ok"));
}
void writelnIfNonVoid(T...)(lazy T a){
     import std.conv;
     static if(T.length) mixin({
         string r,args;
         foreach(i,t;T){
             if(!is(t==void)){
                 r~="auto r_"~to!string(i)~"=";
                 args~="r_"~to!string(i)~",";
             }
             r~="a["~to!string(i)~"];";
         }
         return r~"writeln("~args~");";
     }());
}

(Not sure what you intended the exact rules for emmiting a line feed 
character to be.)




More information about the Digitalmars-d-learn mailing list