Variadic template parameters, refactor a long chain of static if's to 'functions'.

realhet real_het at hotmail.com
Tue Jun 11 09:26:56 UTC 2019


Hi again,

I'm trying to do variadic parameter processing, and I have the 
following function that works fine:

   static bool same(T1, T2)(){
     pragma(msg, "same? "~T1.stringof~" "~T2.stringof);
     return is(immutable(T1)==immutable(T2));
   }

   Btn btn(T...)(string params, T args){
     enum captureIntID = true,
          captureBoolEnabled = true,
          captureFunct = true;

     Args r; //Arg is a struct to store all the possible 
parameters in runtime
     static foreach(a; args){
       //process id parameter
            static if(same!(typeof(a), id)) r.id = a.val;
       else static if(captureIntID && (same!(typeof(a), int) || 
same!(typeof(a), uint))) r.id = a;

       //process enabled/disabled
       else static if(same!(typeof(a), enabled )) r.enabled = 
a.val;
       else static if(same!(typeof(a), disabled)) r.enabled = 
!a.val;
       else static if(captureBoolEnabled && same!(typeof(a), bool) 
) r.enabled = a;

       //process data events
       else static if(same!(typeof(a), onClick  )) 
r.events.onClick   = a.f;
       else static if(same!(typeof(a), onPress  )) 
r.events.onPress   = a.f;
       else static if(same!(typeof(a), onRelease)) 
r.events.onRelease = a.f;
       else static if(same!(typeof(a), onChange )) 
r.events.onChange  = a.f;
       else static if(same!(typeof(a), onTrue   )) r.events.onTrue 
    = a.f;
       else static if(same!(typeof(a), onFalse  )) 
r.events.onFalse   = a.f;
       else static if(same!(typeof(a), onBool   )) r.events.onBool 
    = a.f;
       else static if(typeof(a).stringof.startsWith("void 
delegate()"    )) r.events.onClick = a;
       else static if(typeof(a).stringof.startsWith("void 
delegate(bool)")) r.events.onBool = a;

       else static assert(false, "Unsupported type 
"~typeof(a).stringof);
     }

     return new Btn(params, r.id, r.enabled, r.events);
   }


The long chain of is's are required to be able to show the error 
message at the end when an unhandled parameter type is found.

I will have more of these and want to reuse these ifs in other 
functions as well, so I decided to take out the first 2 if's and 
put it into a template function:

   static bool processId(bool captureIntId, alias r, alias a)(){
     mixin("alias ta = typeof("~a.stringof~");");
     pragma(msg, "ta "~ta.stringof);
          static if(same!(ta, id)) { r = a.val; return true; }
     else static if(captureIntId && (same!(ta, int) || same!(ta, 
uint))) { r = a; return true; }
     else return false;
   }

later I call it with:

   static if(processId!(true, r.id, a)){}
   else static if(...

'a' is the variadic foreach variable (_param_1 and so on),
'r.id' is the result field from an Arg structure.
Both 'a' and 'r.id' are existing and compiling, also the pragma 
messages are good, I see it can find the right types, but I have 
the following error for every variadic parameter:

Error: template instance processId!(true, id, _param_1) 
processId!(true, id, _param_1) is nested in both Args and btn

id is a struct. And also a field in the Args struct. I changed it 
to id1 in the Args struct ant the error remains the same.
Everything resides in the scope of a class called 
ContainerBuilder.

Is there a way to do this elegantly?
Maybe if I put everything in a very large chain of if's and 
enable the required parameters with a set of flags, but that's 
not structured well, and also needs the biggest possible set of 
runtime parameter storage to store the processed parametest.

Here's an example using the above function:
btn(`Yes flex=1`, id(54231), enabled(true), { lastClickedBtn = 
"Yes"; hehe = true; })
checkbox("Checkbox_1", 12345432, (bool b){ hehe = b; })

I will have a lot of controls and a lot of parameter types. I 
wanna do something like in the old VisualBasic, where you can 
skip a lot of default parameters, and also access the only few 
you need by name. Something like this: btn("caption", 
hint:"blabla", icon:"icon.ico"), but as I currently know this is 
not implemented in D.

Thank You in advance!




More information about the Digitalmars-d-learn mailing list