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
Re: inferred size for static array initialization
On Monday, 2 May 2016 at 17:43:56 UTC, Namespace wrote: immutable auto a = [1,2,3].s; Will that have zero run-time overhead compared to: immutable int[3] a = [1,2,3]; ?
Re: inferred size for static array initialization
On 10/18/16 6:35 AM, Nordlöw wrote: On Monday, 2 May 2016 at 17:43:56 UTC, Namespace wrote: immutable auto a = [1,2,3].s; Will that have zero run-time overhead compared to: immutable int[3] a = [1,2,3]; Neither will have zero runtime overhead, but use the disassembler to see if there is a difference. My understanding is that while the compiler used to allocate whenever it saw an array literal (including your above usage), that is no longer the case. -Steve
Re: inferred size for static array initialization
On Tuesday, 18 October 2016 at 10:35:44 UTC, Nordlöw wrote: On Monday, 2 May 2016 at 17:43:56 UTC, Namespace wrote: immutable auto a = [1,2,3].s; Will that have zero run-time overhead compared to: immutable int[3] a = [1,2,3]; ? I'm not quite sure if pragma(inline, true) would result in zero runtime overhead, but without you have 3 lines of assembler more (with gdc). https://godbolt.org/g/JUjP1d https://godbolt.org/g/qaqylp
Re: inferred size for static array initialization
On Monday, 2 May 2016 at 13:00:27 UTC, Erik Smith wrote: 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 Help yourself with a template: import std.traits; auto toStaticArray(alias array)() if (isArray!(typeof(array))) { enum size = array.length; alias T = typeof(array.init[0])[size]; T result = array[0..size]; return result; } enum a = toStaticArray!([1,2,3]); static assert(isStaticArray!(typeof(a))); // success Does it fit ?
Re: inferred size for static array initialization
On Monday, 2 May 2016 at 13:22:01 UTC, Basile B wrote: On Monday, 2 May 2016 at 13:00:27 UTC, Erik Smith wrote: 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 Help yourself with a template: import std.traits; auto toStaticArray(alias array)() if (isArray!(typeof(array))) { enum size = array.length; alias T = typeof(array.init[0])[size]; T result = array[0..size]; return result; } enum a = toStaticArray!([1,2,3]); static assert(isStaticArray!(typeof(a))); // success Does it fit ? Using an enum is probably a bit better auto toStaticArray(alias array)() if (isDynamicArray!(typeof(array)) && array.length) { alias T = typeof(array[0])[array.length]; enum T result = array[0..array.length]; return result; }
Re: inferred size for static array initialization
Am Mon, 02 May 2016 13:00:27 + schrieb Erik Smith : > 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 > Sure, struct S { int a, b; } immutable tab = { static enum S[] s = [ {1,2}, {3,4}, ]; return cast(typeof(s[0])[s.length])s; }(); static assert(isStaticArray!(typeof(tab))); // succeeds -- Marco
Re: inferred size for static array initialization
On 02.05.2016 15:53, Marco Leise wrote: immutable tab = { static enum S[] s = [ `static enum`? What kind of black magic is this?
Re: inferred size for static array initialization
Am Mon, 2 May 2016 18:52:11 +0200 schrieb ag0aep6g : > On 02.05.2016 15:53, Marco Leise wrote: > >immutable tab = { static enum S[] s = [ > > `static enum`? What kind of black magic is this? I don't know, but it works, haha. -- Marco
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
Re: inferred size for static array initialization
On Monday, 2 May 2016 at 13:00:27 UTC, Erik Smith wrote: 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 I still like auto s(T, size_t n)(T[n] arr) { return arr; } auto arr = [1, 2, 3].s; But of course this won't work: int[] a = [1,2,3].s; static assert(isStaticArray!(typeof(a))); // fails Since 'a' is just a slice. But this will work: immutable auto a = [1,2,3].s;
Re: inferred size for static array initialization
On 5/2/16 1:43 PM, Namespace wrote: On Monday, 2 May 2016 at 13:00:27 UTC, Erik Smith wrote: 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 I still like auto s(T, size_t n)(T[n] arr) { return arr; } Interesting. But there is a major problem here... auto arr = [1, 2, 3].s; But of course this won't work: int[] a = [1,2,3].s; static assert(isStaticArray!(typeof(a))); // fails And this is the problem. Since 'a' is just a slice. A slice of a no-longer-existing temporary! Admittedly, this is not an issue with your code, but a deeper issue of allowing slicing of rvalues. But this will work: immutable auto a = [1,2,3].s; You can drop auto. It's just a placeholder for the storage class in the case where a storage class isn't specified. -Steve
Re: inferred size for static array initialization
On Monday, 2 May 2016 at 18:57:49 UTC, Namespace wrote: A slice of a no-longer-existing temporary! Admittedly, this is not an issue with your code, but a deeper issue of allowing slicing of rvalues. This works: int[] as = [1, 2, 3].s; writeln(as[2]); Of course this slice is only valid as long as you dont leave the scope. That's maybe what you tried to say, right?
Re: inferred size for static array initialization
A slice of a no-longer-existing temporary! Admittedly, this is not an issue with your code, but a deeper issue of allowing slicing of rvalues. This works: int[] as = [1, 2, 3].s; writeln(as[2]); Bug or feature? Or did I may misunderstood you? You can drop auto. It's just a placeholder for the storage class in the case where a storage class isn't specified. Right, I forgot, it's a bit since I wrote something in D.
Re: inferred size for static array initialization
On 5/2/16 3:02 PM, Namespace wrote: On Monday, 2 May 2016 at 18:57:49 UTC, Namespace wrote: A slice of a no-longer-existing temporary! Admittedly, this is not an issue with your code, but a deeper issue of allowing slicing of rvalues. This works: int[] as = [1, 2, 3].s; writeln(as[2]); Of course this slice is only valid as long as you dont leave the scope. That's maybe what you tried to say, right? No, because 'as' is pointing at stack space no longer allocated. It may work, and it may not, but having it work is not proof that it's sound. To make things clear, this is what your code effectively does: int[] as = void; { auto _tmp = [1, 2, 3].s; as = _tmp; } Which is not the same thing as having the static array a defined stack variable in the same scope. -Steve
Re: inferred size for static array initialization
On Monday, 2 May 2016 at 19:08:52 UTC, Steven Schveighoffer wrote: On 5/2/16 3:02 PM, Namespace wrote: On Monday, 2 May 2016 at 18:57:49 UTC, Namespace wrote: A slice of a no-longer-existing temporary! Admittedly, this is not an issue with your code, but a deeper issue of allowing slicing of rvalues. This works: int[] as = [1, 2, 3].s; writeln(as[2]); Of course this slice is only valid as long as you dont leave the scope. That's maybe what you tried to say, right? No, because 'as' is pointing at stack space no longer allocated. It may work, and it may not, but having it work is not proof that it's sound. To make things clear, this is what your code effectively does: int[] as = void; { auto _tmp = [1, 2, 3].s; as = _tmp; } Which is not the same thing as having the static array a defined stack variable in the same scope. -Steve The assembler looks different than that but I may be wrong and I only looked at gdc. But anyway, that means with 'pragma(inline, true)' I'm save. Is that right?
Re: inferred size for static array initialization
On 5/2/16 3:12 PM, Namespace wrote: On Monday, 2 May 2016 at 19:08:52 UTC, Steven Schveighoffer wrote: On 5/2/16 3:02 PM, Namespace wrote: On Monday, 2 May 2016 at 18:57:49 UTC, Namespace wrote: A slice of a no-longer-existing temporary! Admittedly, this is not an issue with your code, but a deeper issue of allowing slicing of rvalues. This works: int[] as = [1, 2, 3].s; writeln(as[2]); Of course this slice is only valid as long as you dont leave the scope. That's maybe what you tried to say, right? No, because 'as' is pointing at stack space no longer allocated. It may work, and it may not, but having it work is not proof that it's sound. To make things clear, this is what your code effectively does: int[] as = void; { auto _tmp = [1, 2, 3].s; as = _tmp; } Which is not the same thing as having the static array a defined stack variable in the same scope. The assembler looks different than that but I may be wrong and I only looked at gdc. But anyway, that means with 'pragma(inline, true)' I'm save. Is that right? The assembler might be safe in some instances, but that doesn't reflect the original internal representation in the compiler. Some other configuration of calls may allow the compiler to reuse that memory, and then you run into problems. I'm wondering if you used my rewrite if it would actually output the same thing? But in any case, I don't know the answer to the pragma(inline) thing. I would guess it is subject to the same issues, but I'm not 100% sure. -Steve
Re: inferred size for static array initialization
The assembler might be safe in some instances, but that doesn't reflect the original internal representation in the compiler. Some other configuration of calls may allow the compiler to reuse that memory, and then you run into problems. I'm wondering if you used my rewrite if it would actually output the same thing? Not quite. Look for yourself: https://godbolt.org/g/kO8hdW https://godbolt.org/g/KCfYPy
Re: inferred size for static array initialization
On 5/2/16 3:38 PM, Namespace wrote: The assembler might be safe in some instances, but that doesn't reflect the original internal representation in the compiler. Some other configuration of calls may allow the compiler to reuse that memory, and then you run into problems. I'm wondering if you used my rewrite if it would actually output the same thing? Not quite. Look for yourself: https://godbolt.org/g/kO8hdW https://godbolt.org/g/KCfYPy Except for offsets, it looks identical. May be the compiler puts things in different spots for different ways of writing. But the thing that's not disclosed here is: what happens when the compiler feels the need to reuse that stack space? Your example doesn't have anything that may compete for the space, it just returns after this is over. For example, define a static array of exactly the same size to use after the call: int[3] x; Now, see if x is pigeonholed into that same place your temporary return existed (and therefore 'as' points at it). I'm still fully on the side of this being unsafe. -Steve
Re: inferred size for static array initialization
On Monday, 2 May 2016 at 20:05:15 UTC, Steven Schveighoffer wrote: On 5/2/16 3:38 PM, Namespace wrote: The assembler might be safe in some instances, but that doesn't reflect the original internal representation in the compiler. Some other configuration of calls may allow the compiler to reuse that memory, and then you run into problems. I'm wondering if you used my rewrite if it would actually output the same thing? Not quite. Look for yourself: https://godbolt.org/g/kO8hdW https://godbolt.org/g/KCfYPy Except for offsets, it looks identical. May be the compiler puts things in different spots for different ways of writing. But the thing that's not disclosed here is: what happens when the compiler feels the need to reuse that stack space? Your example doesn't have anything that may compete for the space, it just returns after this is over. For example, define a static array of exactly the same size to use after the call: int[3] x; Now, see if x is pigeonholed into that same place your temporary return existed (and therefore 'as' points at it). I'm still fully on the side of this being unsafe. -Steve I used it very often, but always assigned the result to an auto-type variable, never to a slice.
Re: inferred size for static array initialization
On 5/2/16 4:14 PM, Namespace wrote: I used it very often, but always assigned the result to an auto-type variable, never to a slice. Using auto is fine, but the slice should not happen if you are assigning slice to a local var. There is a bug report on this: https://issues.dlang.org/show_bug.cgi?id=12625, though it's not as focused as I think it should be. -Steve
Re: inferred size for static array initialization
On Monday, 2 May 2016 at 17:43:56 UTC, Namespace wrote: I still like auto s(T, size_t n)(T[n] arr) { return arr; } Wooah, this trick is awesome. But actually it does the same thing that what I've proposed before. Exactly the same code is generated. So I'd say that it's rather a matter of readability. https://godbolt.org/g/wGTs52 https://godbolt.org/g/cXECyO