Re: staticMap but with two arguments
On 2/9/23 12:45, John Chapman wrote: > On Thursday, 9 February 2023 at 19:17:55 UTC, Ali Çehreli wrote: >> I could not figure out eliminating the hard-coded 4. Can we introspect >> the parameter list of a template like 'fun' in the example? If we >> could, then we could get 4 that way. > > Thank you for this. I don't mind hard-coding the N argument. > TemplateArgsOf needs an instantiated template but maybe ```enum N = > count(fun.stringof, ',') + 1``` is good enough. Hopefully but very fragile: template t(int[] T = [ 1, 2 ]) {} void main() { import std.algorithm : count; enum N = count(t.stringof, ',') + 1; static assert(N == 1); // FAILS } Same thing with any other thing with comma in it e.g. template t(T = anotherTemplate!(1, 2)) {} Ali
Re: staticMap but with two arguments
On Thursday, 9 February 2023 at 19:17:55 UTC, Ali Çehreli wrote: I could not figure out eliminating the hard-coded 4. Can we introspect the parameter list of a template like 'fun' in the example? If we could, then we could get 4 that way. Thank you for this. I don't mind hard-coding the N argument. TemplateArgsOf needs an instantiated template but maybe ```enum N = count(fun.stringof, ',') + 1``` is good enough.
Re: staticMap but with two arguments
On 2/8/23 12:04, John Chapman wrote: > rather than write it manually for each N? import std.meta : AliasSeq; template pickArgs(size_t totalElements, size_t argsPerElement, size_t whichElement, args...) { alias pickArgs = AliasSeq!(); static foreach (a; 0 .. argsPerElement) { pickArgs = AliasSeq!(pickArgs, args[whichElement + a * totalElements]); } } template staticMapN(size_t N, alias fun, args...) { static assert(N != 0, "N must be non-zero."); static assert((args.length % N) == 0, "Mismatched number of arguments"); enum totalElements = args.length / N; alias staticMapN = AliasSeq!(); static foreach (e; 0 .. totalElements) { staticMapN = AliasSeq!(staticMapN, fun!(pickArgs!(totalElements, N, e, args))); } } // An example struct with some template parameters struct S(T, size_t length, size_t foo, size_t bar) { } // An example template that creates instantiations of the S template template Instantiate(T, size_t length, size_t foo, size_t bar) { alias Instantiate = S!(T, length, foo, bar); } // Compile-time argument sets for three instantiations of the S template alias myTypes = AliasSeq!(int, double, long); alias mySizes = AliasSeq!(1, 2, 3); alias myFoos = AliasSeq!(42, 43, 44); alias myBars = AliasSeq!(100, 200, 300); // A test with those 4 sets of template arguments alias result = staticMapN!(4, Instantiate, myTypes, mySizes, myFoos, myBars); pragma(msg, result); void main() { } I could not figure out eliminating the hard-coded 4. Can we introspect the parameter list of a template like 'fun' in the example? If we could, then we could get 4 that way. Ali
Re: staticMap but with two arguments
On Monday, 6 February 2023 at 09:17:07 UTC, Ali Çehreli wrote: I adapted staticMap's implementation to two sets of arguments: So I've got this implementation, but wonder if I can generalise the arg splitting portion rather than write it manually for each N? ```d template staticMapN(size_t N, alias fun, args...) if (args.length % N == 0) { alias staticMapN = AliasSeq!(); static foreach (i; 0 .. args.length / N) static if (N == 1) staticMapN = AliasSeq!(staticMapN, fun!(args)); else static if (N == 2) staticMapN = AliasSeq!(staticMapN, fun!(args[0 .. $ / N][i], args[$ / N .. ($ / N) * 2][i])); else static if (N == 3) staticMapN = AliasSeq!(staticMapN, fun!(args[0 .. $ / N][i], args[$ / N .. ($ / N) * 2][i], args[($ / N) * 2 .. ($ / N) * 3][i])); // etc } ```
Re: staticMap but with two arguments
On Monday, 6 February 2023 at 09:17:07 UTC, Ali Çehreli wrote: I adapted staticMap's implementation to two sets of arguments: Thanks Ali, that's perfect. I thought of splitting the args in half a few hours later but hadn't got around to trying it.
Re: staticMap but with two arguments
On 2/5/23 17:20, John Chapman wrote: > staticMap's "fun" can only be > instantiated with a single argument, while I need it to work with two. I adapted staticMap's implementation to two sets of arguments: import std.meta : AliasSeq; // The first half of 'args' is the "first arguments" and // the second half is the "second arguments". // // (This can be generalized to N sets of arguments.) template staticMap2(alias fun, args...) { alias firsts = args[0 .. $ / 2]; alias seconds = args[$ / 2 .. $]; static assert(firsts.length == seconds.length, "Mismatched number of first and second arguments"); alias staticMap2 = AliasSeq!(); static foreach (i; 0 .. firsts.length) { staticMap2 = AliasSeq!(staticMap2, fun!(firsts[i], seconds[i])); } } // An example struct with two template parameters struct S(T, size_t length) { } // An example template that creates instantiations of the S template // (This can be generalized to instantiation of any template.) template Instantiate(T, size_t length) { alias Instantiate = S!(T, length); } // An example use alias myTypes = AliasSeq!(int, double, long); alias mySizes = AliasSeq!(1, 2, 3); alias result = staticMap2!(Instantiate, myTypes, mySizes); pragma(msg, result); void main() { } Ali
staticMap but with two arguments
I have two AliasSeqs: one containing a function's parameters (SourceSeq), the other containing the types I want to convert said parameters to (TargetSeq). I'd use something like staticMap to call the conversion function with both a parameter from SourceSeq and a type from TargetSeq, and return an AliasSeq of converted values which will be forwarded to another function. staticMap's "fun" can only be instantiated with a single argument, while I need it to work with two. E.g.: ``` template toTarget(alias source, Target) { static if (is(typeof(source) == int) && is(Target == string)) // for example, convert int to string } alias TargetSeq = Parameters!targetFunc; auto wrapperFunc(A...)(A) { alias SourceSeq = __traits(parameters); return targetFunc(staticMap!(toTarget, SourceSeq)); // How would I call staticMap (or something similar) with SourceSeq *and* TargetSeq? } ``` I could build the list of converted values manually but I wanted something smart (like staticMap) to do it inline. I thought ApplyLeft/Right could help but couldn't get my head around it.