Re: parameter pack to inputRange
On Sunday, 8 May 2016 at 23:49:40 UTC, Ali Çehreli wrote: On 05/08/2016 04:48 PM, Erik Smith wrote: On Sunday, 8 May 2016 at 22:37:44 UTC, Dicebot wrote: On Sunday, 8 May 2016 at 14:11:31 UTC, Ali Çehreli wrote: E front() { final switch (index) { /* static */ foreach (i, arg; Args) { case i: return arg; } } } AFAIK, this will do funny things with referencing stack if arguments are variables and not literals. Thanks! The static array version works for me too. It would be good to understand more about what is going on. It looks like the cost of the static array is an extra copy for each element. Maybe there is still a way to avoid that. I had to change one line of your test code. Dicebot's code work with it: auto toInputRange (T...) (T args) @nogc { import std.traits : CommonType; alias E = CommonType!T; struct Range { E[T.length] args; size_t index; E front () { return args[index]; } void popFront () { ++index; } bool empty () { return index >= args.length; } } Range range; foreach (i, ref arg; args) range.args[i] = arg; return range; } static void foo(Args...)(Args args) { import std.container.array; auto array = Array!int(toInputRange(args)); // <-- HERE foreach(a; array) { import std.stdio : writeln; writeln("e: ", a); } } void main ( ) { import std.stdio; writeln(toInputRange(1, 2, 3)); foo(1,2,3); } It used to be toInputRange!(args) Ali I did notice that but forgot to mention it - thanks for clarifying. Again it definitely works but it would be nice to find a non-copy solution. I tried to form a static array of pointers to the args (see below). It compiled but the output was bad. I would expect that taking the address of the arguments should be safe as long as you are in the called function. auto toInputRange (T...) (T args) @nogc { import std.traits : CommonType; alias E = CommonType!T; struct Range { alias P = E*; P[T.length] args; size_t index; E front () { return *args[index]; } void popFront () { ++index; } bool empty () { return index >= args.length; } } Range range; foreach (i, ref arg; args) range.args[i] = &arg; return range; }
Re: parameter pack to inputRange
On Sunday, 8 May 2016 at 22:37:44 UTC, Dicebot wrote: On Sunday, 8 May 2016 at 14:11:31 UTC, Ali Çehreli wrote: E front() { final switch (index) { /* static */ foreach (i, arg; Args) { case i: return arg; } } } AFAIK, this will do funny things with referencing stack if arguments are variables and not literals. Thanks! The static array version works for me too. It would be good to understand more about what is going on. It looks like the cost of the static array is an extra copy for each element. Maybe there is still a way to avoid that.
Re: parameter pack to inputRange
On Sunday, 8 May 2016 at 14:11:31 UTC, Ali Çehreli wrote: On 05/05/2016 11:08 PM, Dicebot wrote: > Unless parameter list is very (very!) long, I'd suggest to simply copy > it into a stack struct. Something like this: > > auto toInputRange (T...) (T args) > { > struct Range > { > T args; > size_t index; > > T[0] front () { return args[index]; } > void popFront () { ++index; } > bool empty () { return index >= args.length; } > } > > return Range(args, 0); > } I wanted this syntax to work but when I tested I saw that T does not expand to struct members. I like Alex Parrill's only() solution but it allocates a dynamic array as well by doing the equivalent of [args] in the guts of its implementation. As Dicebot said, unless there are tons of arguments, I think the following is the best as it is @nogc. It executes a switch statement for each front() call though. And I like the CommonType!T idea there. import std.stdio; import std.string; /* Support empty Args? */ @nogc pure nothrow auto toInputRange(Args...)() { struct Range { size_t index; bool empty() { return index >= Args.length; } void popFront() { ++index; } import std.traits : CommonType; alias E = CommonType!Args; E front() { final switch (index) { /* static */ foreach (i, arg; Args) { case i: return arg; } } } } return Range(); } unittest { import std.traits; import std.range; static assert(isInputRange!(ReturnType!(toInputRange!(1; } void main() { auto r = toInputRange!(1, 2.5, 3); writeln(r); } Ali I like this solution and it's exactly what I was looking for. However, I'm having an issue when I try to apply it with an actual variadic function. This seems like a DMD bug. static void foo(Args...)(Args args) { import std.container.array; auto array = Array!int(toInputRange!(args)); foreach(a; array) { writeln("e: ", a); } } foo(1,2,3); e:1431827808 e:32767 e:1254116144
Re: parameter pack to inputRange
On Friday, 6 May 2016 at 05:20:50 UTC, Ali Çehreli wrote: On 05/05/2016 10:00 PM, Erik Smith wrote: Is there an existing way to adapt a parameter pack to an input range? I would like to construct an array with it. Example: void run(A...) (A args) { Array!int a(toInputRange(args)); } Just initialize an array with the arguments: void run(A...) (A args) { writeln([args]); } Ali That's allocating a dynamic array though, right? It seems like there should be a non-GC adaptor for this purpose (especially since I'm using std.container.array). erik
parameter pack to inputRange
Is there an existing way to adapt a parameter pack to an input range? I would like to construct an array with it. Example: void run(A...) (A args) { Array!int a(toInputRange(args)); }
Re: template auto instantiation when parameters empty
On Thursday, 5 May 2016 at 16:12:40 UTC, Steven Schveighoffer wrote: On 5/5/16 12:10 AM, Erik Smith wrote: I want to have a struct template auto instantiate when the template parameters are defaulted or missing. Example: struct Resource(T=int) { static auto create() {return Resource(null);} this(string s) {} } auto resource = Resource.create; As a plain struct it works, but not as a template: struct Resource { // works struct Resource() { // fails struct Resource(T=int) { // fails At the call site, this works, but I'm hoping for a few less symbols: auto resource = Resource!().create; Any ideas? Instead of static method, use an external factory method: static auto createResource(T = int)() { return Resource!T(null); } And I wouldn't bother with making Resource's T have a default, as you'd still have to instantiate it with Resource!() to get the default. -Steve Alias works at the cost of adding a 2nd type name: alias Res = Resource!(); auto res = Res.create The other problem is that the alias definition by itself instantiates, which I can't afford. I have createResource() now, it just doesn't fit well with the rest of the calling styles. There is also this approach, which might be slightly more idiomatic struct Resource(T) {} struct Policy {} auto create(alias T)() { T!Policy r; return r; } auto r = create!Resource;
template auto instantiation when parameters empty
I want to have a struct template auto instantiate when the template parameters are defaulted or missing. Example: struct Resource(T=int) { static auto create() {return Resource(null);} this(string s) {} } auto resource = Resource.create; As a plain struct it works, but not as a template: struct Resource { // works struct Resource() { // fails struct Resource(T=int) { // fails At the call site, this works, but I'm hoping for a few less symbols: auto resource = Resource!().create; Any ideas?
Re: what is equivalent to template template
You're close. An `alias` template parameter can be any symbol, including a template. But you can't pass in a template as a runtime parameter, so having `F f` in your parameters list is wrong (there's nothing to pass anyway; you already have the template, which is F). static void call(alias F, A...)(A a) { F(a); } Then instantiate and call the `call` function with the template you want: call!myVariadict(1,2,3); Works. Thanks!
Re: constructed variadic call
I don't think it's possible to call a vararg function whose number of arguments is only known at runtime, for the same reasons it is impossible in C [1]. Your switch statement is probably the best you can do, other than rewriting the API to not use varargs (which, depending on what the function is doing, I would recommend). You can possibly use string mixins or static foreach to avoid repeating the case clauses. [1] Populating a va_list: http://stackoverflow.com/questions/988290/populating-a-va-list That was fast :). The generation idea helps a little - thanks. It works though and I can't use va_list in this case. erik
what is equivalent to template template
C++ has template templates. I'm not sure how to achieve the same effect where (in example below) the template function myVariadic is passed to another function. void myVaridatic(A...)(A a) {} static void call(alias F,A...)(F f,A a) { f(a); } void foo() { call(myVaridatic,1,2,3); }
Re: constructed variadic call
On Monday, 2 May 2016 at 18:56:59 UTC, Stefan Koch wrote: On Monday, 2 May 2016 at 18:22:52 UTC, Erik Smith wrote: Is there way to construct an "argument pack" from a non-static array (like the switch below)? I need to transport a variadic call through a void*. switch (a.length) { case 1: foo(a[1]); break; case 2: foo(a[1], a[2]); break; case 3: foo(a[1], a[2], a[3]); break; ... } Yes there is. Using a string mixin. I'm not sure how to apply mixins here because they require compile time evaluation and a.length is runtime. Ideas? erik
constructed variadic call
Is there way to construct an "argument pack" from a non-static array (like the switch below)? I need to transport a variadic call through a void*. switch (a.length) { case 1: foo(a[1]); break; case 2: foo(a[1], a[2]); break; case 3: foo(a[1], a[2], a[3]); break; ... }
Re: inferred size for static array initialization
I tried to combine the two solutions (Basile with the wrapper, Marco with the struct initializer support) but it didn't work. The struct initializer is not a array literal (seems obvious now). I might go with the 2nd but it's pretty heavy just to get the size. Thanks. struct S { int a, b; } auto toStaticArray(alias array)() { struct S { int a, b; } immutable tab = { static enum S[] s = array; return cast(typeof(s[0])[s.length])s; }(); return tab; } enum a = toStaticArray!([{1,2},{3,4}]); // error
inferred size for static array initialization
Is there a way to initialize a static array and have it's size inferred (and that works for arrays of structs using braced literals)? This would make it easier to maintain longer static array definitions. The code below doesn't work when removing the array size even though the array is declared as static immutable. import std.traits; static immutable int[] a = [1,2,3]; static assert(isStaticArray!(typeof(a))); // fails