digitalmars.D.learn - Can't use variadic arguments to functions that use templates
- JS (31/31) Jul 20 2013 variadic parameters are suppose to make life easier but it seems
- bearophile (13/20) Jul 20 2013 Try this:
- JS (3/26) Jul 20 2013 ;/ I could have swore I tried that ;/
- JS (4/27) Jul 20 2013 is there any way to pass t directly to A?
- Jesse Phillips (22/25) Jul 20 2013 template A(size_t L) {
- JS (22/48) Jul 21 2013 I know I tried that but:
- Jesse Phillips (23/34) Jul 22 2013 My method doesn't make any calls, your foo is a called at
- JS (44/81) Jul 23 2013 I don't think you understand(or I've already got confused)...
- Jesse Phillips (16/21) Jul 23 2013 I'll stick with the reduced example, maybe you can apply it to
- JS (3/25) Jul 23 2013 What good does that do?
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (15/42) Jul 23 2013 Just pass the runtime values to the template:
- Jesse Phillips (5/16) Jul 23 2013 Ah, I understand now you're interested in:
- H. S. Teoh (59/79) Jul 23 2013 Is this by any chance related to that other thread about compile-time
- JS (3/86) Jul 23 2013 Thanks, I'll check it out when I get a chance and report back. It
variadic parameters are suppose to make life easier but it seems those don't work with templates. template A(int L) { ... } void foo(T)(string s, T t...) { A!(t.length); } gives error t can't be read at compile time. I understand in general why this works BUT I will only ever use foo where the number of arguments are known at compile time. Therefor to get the code to work I have to revert back to the old way of overloading foo many times to emulate variadic parameters. Essentially all I want to do is to use foo like foo("a", "b", "c", 'd', s, ...) but the number of arguments is fixed at compile time(almost all arguments are, aren't they?). Here is a challenge: Write a function that accepts any number of string or character variables or literals and returns the concatenates them efficiently as possible(as efficient as fixed arguments). e.g., foo1(string s) { return s; } foo2(string s1, string s2) { return s1~s2; } etc... if we had compile time variadic parameters, we could do something like foo(T t$...) { return mixin(concat!t); } where concat produces the string t[0]~t[1]~t[2]... which produces the same code as the overloaded case, but must simpler. I don't think this is possible because there is no static version of variadic arguments, i.e., one who's length is always known at compile time.
Jul 20 2013
JS:variadic parameters are suppose to make life easier but it seems those don't work with templates. template A(int L) { ... } void foo(T)(string s, T t...) { A!(t.length); }Try this: template A(size_t L) { enum A = L; } void foo(T...)(string s, T t) { auto n = A!(t.length); } void main() { foo("x", 1, 2); } Bye, bearophile
Jul 20 2013
On Saturday, 20 July 2013 at 17:39:59 UTC, bearophile wrote:JS:;/ I could have swore I tried that ;/ Thanks though! ;)variadic parameters are suppose to make life easier but it seems those don't work with templates. template A(int L) { ... } void foo(T)(string s, T t...) { A!(t.length); }Try this: template A(size_t L) { enum A = L; } void foo(T...)(string s, T t) { auto n = A!(t.length); } void main() { foo("x", 1, 2); } Bye, bearophile
Jul 20 2013
On Saturday, 20 July 2013 at 17:39:59 UTC, bearophile wrote:JS:is there any way to pass t directly to A? template A(T...) doesn't seem work nor does using an alias. (or at least, when I try to foreach over it, it doesn't work).variadic parameters are suppose to make life easier but it seems those don't work with templates. template A(int L) { ... } void foo(T)(string s, T t...) { A!(t.length); }Try this: template A(size_t L) { enum A = L; } void foo(T...)(string s, T t) { auto n = A!(t.length); } void main() { foo("x", 1, 2); } Bye, bearophile
Jul 20 2013
On Saturday, 20 July 2013 at 18:27:23 UTC, JS wrote:is there any way to pass t directly to A? template A(T...) doesn't seem work nor does using an alias. (or at least, when I try to foreach over it, it doesn't work).template A(size_t L) { enum A = L; } template B(T...) { void B(T b) { import std.stdio; foreach(Type; T) { pragma(msg, Type.stringof); } foreach(v; b) { writeln(v); } }} void foo(T...)(string s, T t) { auto n = A!(t.length); B(t);// t is runtime information // T is compile time information } void main() { foo("x", 1, 2); }
Jul 20 2013
On Saturday, 20 July 2013 at 18:57:18 UTC, Jesse Phillips wrote:On Saturday, 20 July 2013 at 18:27:23 UTC, JS wrote:I know I tried that but: import std.cstream, std.stdio; template B(T...) { string B(T b) { string s; foreach(Type; T) pragma(msg, Type.stringof); foreach(v; b) s ~= v.stringof; return s; } } void foo(T...)(T t) { pragma(msg, B(t)); } void main() { foo("x", "a", "b"); din.getc(); } does work. I need to have B generate compile time code so it is efficient. Your method calls an actual function at runtime so it is nearly as fast as it can be.is there any way to pass t directly to A? template A(T...) doesn't seem work nor does using an alias. (or at least, when I try to foreach over it, it doesn't work).template A(size_t L) { enum A = L; } template B(T...) { void B(T b) { import std.stdio; foreach(Type; T) { pragma(msg, Type.stringof); } foreach(v; b) { writeln(v); } }} void foo(T...)(string s, T t) { auto n = A!(t.length); B(t);// t is runtime information // T is compile time information } void main() { foo("x", 1, 2); }
Jul 21 2013
On Sunday, 21 July 2013 at 07:22:08 UTC, JS wrote:void foo(T...)(T t) { pragma(msg, B(t)); } void main() { foo("x", "a", "b"); din.getc(); } does work. I need to have B generate compile time code so it is efficient. Your method calls an actual function at runtime so it is nearly as fast as it can be.My method doesn't make any calls, your foo is a called at runtime. There is no way to observe a function at compile time; ctfeWriteln does not exist. Also don't stringof variable v (I assume you want the value and not the symbol concatenated. template B(T...) { string B(T b) { string s; foreach(Type; T) pragma(msg, Type.stringof); foreach(v; b) s ~= v; return s; } } string foo(T...)(T t) { return B(t); } void main() { enum forced = foo("x", "a", "b"); pragma(msg, forced); din.getc(); }
Jul 22 2013
On Monday, 22 July 2013 at 16:48:56 UTC, Jesse Phillips wrote:On Sunday, 21 July 2013 at 07:22:08 UTC, JS wrote:I don't think you understand(or I've already got confused)... I'm trying to use B has a mixin(I don't think I made this clear). I can't use it as a normal function. e.g., I can't seem to do mixin(B(t)). If I could, this would definitely solve my problem. Here is a real world example: template VariadicLoop(T...) { pragma(msg, T); string VariadicLoop(T t) { string s; foreach(k; T) s ~= k.stringof; foreach(v; t) s ~= v; return s; } //enum tVariadicLoop = eval(); //pragma(msg, tVariadicLoop); } string join(T...)(string delim, T t) { return mixin(VariadicLoop(t)); } VariadicLoop should join the strings passed to join(producing whatever code is necessary to do this efficiently. e.g., join(",", "a", s) should result in the code for join: { return "a"~","~s; // s maybe t[1] or something } This is the most efficient way to join rather than using a foreach over an array of strings or something or another. (VariadicLoop could handle string[]'s and insert the appropriate code to join them) The goal I'm trying to solve is efficiently deal with variadic arguments that are compile time calculable along with mixing in the runtime aspect. Basically: get the compiler to do all the work it can before having it done at runtime. if we are passing string literals to join then they can be joined at compile time. If we are passing a combination of string literals, string variables, and string arrays then we deal with each part efficiently as possible.void foo(T...)(T t) { pragma(msg, B(t)); } void main() { foo("x", "a", "b"); din.getc(); } does work. I need to have B generate compile time code so it is efficient. Your method calls an actual function at runtime so it is nearly as fast as it can be.My method doesn't make any calls, your foo is a called at runtime. There is no way to observe a function at compile time; ctfeWriteln does not exist. Also don't stringof variable v (I assume you want the value and not the symbol concatenated. template B(T...) { string B(T b) { string s; foreach(Type; T) pragma(msg, Type.stringof); foreach(v; b) s ~= v; return s; } } string foo(T...)(T t) { return B(t); } void main() { enum forced = foo("x", "a", "b"); pragma(msg, forced); din.getc(); }
Jul 23 2013
On Tuesday, 23 July 2013 at 14:03:01 UTC, JS wrote:I don't think you understand(or I've already got confused)... I'm trying to use B has a mixin(I don't think I made this clear). I can't use it as a normal function. e.g., I can't seem to do mixin(B(t)). If I could, this would definitely solve my problem.I'll stick with the reduced example, maybe you can apply it to the real world: template B(T...) { string B(T b) { string s; foreach(i, Type; T) s ~= Type.stringof ~ " " ~ b[i] ~ ";\n"; return s; } } void main() { enum forced = B("x", "a", "b"); pragma(msg, forced); mixin(forced); }
Jul 23 2013
On Tuesday, 23 July 2013 at 16:15:03 UTC, Jesse Phillips wrote:On Tuesday, 23 July 2013 at 14:03:01 UTC, JS wrote:What good does that do? What if I want to use a run-time variable in the mix?I don't think you understand(or I've already got confused)... I'm trying to use B has a mixin(I don't think I made this clear). I can't use it as a normal function. e.g., I can't seem to do mixin(B(t)). If I could, this would definitely solve my problem.I'll stick with the reduced example, maybe you can apply it to the real world: template B(T...) { string B(T b) { string s; foreach(i, Type; T) s ~= Type.stringof ~ " " ~ b[i] ~ ";\n"; return s; } } void main() { enum forced = B("x", "a", "b"); pragma(msg, forced); mixin(forced); }
Jul 23 2013
On 07/23/2013 09:22 AM, JS wrote:On Tuesday, 23 July 2013 at 16:15:03 UTC, Jesse Phillips wrote:Makes a string, mixes it into the source code and then compiles it.On Tuesday, 23 July 2013 at 14:03:01 UTC, JS wrote:What good does that do?I don't think you understand(or I've already got confused)... I'm trying to use B has a mixin(I don't think I made this clear). I can't use it as a normal function. e.g., I can't seem to do mixin(B(t)). If I could, this would definitely solve my problem.I'll stick with the reduced example, maybe you can apply it to the real world: template B(T...) { string B(T b) { string s; foreach(i, Type; T) s ~= Type.stringof ~ " " ~ b[i] ~ ";\n"; return s; } } void main() { enum forced = B("x", "a", "b"); pragma(msg, forced); mixin(forced); }What if I want to use a run-time variable in the mix?Just pass the runtime values to the template: import std.stdio; void main(string[] args) { if (args.length > 2) { writeln(B(args[1], args[2])); } } $ ./deneme abc xyz string abc; string xyz; That is pretty amazing that the same function can be called at compile time and runtime. Ali
Jul 23 2013
On Tuesday, 23 July 2013 at 16:22:38 UTC, JS wrote:On Tuesday, 23 July 2013 at 16:15:03 UTC, Jesse Phillips wrote:Ah, I understand now you're interested in: string concat(alias Data...)() { ... } This does not exist, but maybe it should... I don't know of a workaround to get this behavior.On Tuesday, 23 July 2013 at 14:03:01 UTC, JS wrote:What good does that do? What if I want to use a run-time variable in the mix?I don't think you understand(or I've already got confused)... I'm trying to use B has a mixin(I don't think I made this clear). I can't use it as a normal function. e.g., I can't seem to do mixin(B(t)). If I could, this would definitely solve my problem....[Code]...
Jul 23 2013
On Tue, Jul 23, 2013 at 08:54:12PM +0200, Jesse Phillips wrote:On Tuesday, 23 July 2013 at 16:22:38 UTC, JS wrote:Is this by any chance related to that other thread about compile-time optimized join()? 'cos if it is, I've already solved the problem via templates: import std.stdio; template tuple(args...) { alias tuple = args; } /** * Given a tuple of strings, returns a tuple in which all adjacent compile-time * readable strings are concatenated. */ template tupleReduce(args...) { static if (args.length > 1) { static if (is(typeof(args[0])==string) && __traits(compiles, { enum x = args[0]; })) { static if (is(typeof(args[1])==string) && __traits(compiles, { enum x = args[1]; })) { alias tupleReduce = tupleReduce!(args[0] ~ args[1], args[2..$]); } else { alias tupleReduce = tuple!(args[0], args[1], tupleReduce!(args[2..$])); } } else { alias tupleReduce = tuple!(args[0], tupleReduce!(args[1..$])); } } else { alias tupleReduce = args; } } void main() { string x = "runtime1"; string y = "runtime2"; auto arr = [ tupleReduce!("a", "b", x, "c", "d", y, "e", "f", "g", x) ]; writeln(arr); } The output is: ["ab", "runtime1", "cd", "runtime2", "efg", "runtime1"] All compile-time readable strings in the list have been concatenated at compile-time. T -- I don't trust computers, I've spent too long programming to think that they can get anything right. -- James MillerOn Tuesday, 23 July 2013 at 16:15:03 UTC, Jesse Phillips wrote:Ah, I understand now you're interested in: string concat(alias Data...)() { ... } This does not exist, but maybe it should... I don't know of a workaround to get this behavior.On Tuesday, 23 July 2013 at 14:03:01 UTC, JS wrote:What good does that do? What if I want to use a run-time variable in the mix?I don't think you understand(or I've already got confused)... I'm trying to use B has a mixin(I don't think I made this clear). I can't use it as a normal function. e.g., I can't seem to do mixin(B(t)). If I could, this would definitely solve my problem....[Code]...
Jul 23 2013
On Tuesday, 23 July 2013 at 19:14:26 UTC, H. S. Teoh wrote:On Tue, Jul 23, 2013 at 08:54:12PM +0200, Jesse Phillips wrote:Thanks, I'll check it out when I get a chance and report back. It looks like it solves the problem.On Tuesday, 23 July 2013 at 16:22:38 UTC, JS wrote:Is this by any chance related to that other thread about compile-time optimized join()? 'cos if it is, I've already solved the problem via templates: import std.stdio; template tuple(args...) { alias tuple = args; } /** * Given a tuple of strings, returns a tuple in which all adjacent compile-time * readable strings are concatenated. */ template tupleReduce(args...) { static if (args.length > 1) { static if (is(typeof(args[0])==string) && __traits(compiles, { enum x = args[0]; })) { static if (is(typeof(args[1])==string) && __traits(compiles, { enum x = args[1]; })) { alias tupleReduce = tupleReduce!(args[0] ~ args[1], args[2..$]); } else { alias tupleReduce = tuple!(args[0], args[1], tupleReduce!(args[2..$])); } } else { alias tupleReduce = tuple!(args[0], tupleReduce!(args[1..$])); } } else { alias tupleReduce = args; } } void main() { string x = "runtime1"; string y = "runtime2"; auto arr = [ tupleReduce!("a", "b", x, "c", "d", y, "e", "f", "g", x) ]; writeln(arr); } The output is: ["ab", "runtime1", "cd", "runtime2", "efg", "runtime1"] All compile-time readable strings in the list have been concatenated at compile-time. TOn Tuesday, 23 July 2013 at 16:15:03 UTC, Jesse Phillips wrote:Ah, I understand now you're interested in: string concat(alias Data...)() { ... } This does not exist, but maybe it should... I don't know of a workaround to get this behavior.On Tuesday, 23 July 2013 at 14:03:01 UTC, JS wrote:What good does that do? What if I want to use a run-time variable in the mix?I don't think you understand(or I've already got confused)... I'm trying to use B has a mixin(I don't think I made this clear). I can't use it as a normal function. e.g., I can't seem to do mixin(B(t)). If I could, this would definitely solve my problem....[Code]...
Jul 23 2013