July 05, 2016 Re: Initializing static array with contents of (static and dynamic) arrays | ||||
---|---|---|---|---|
| ||||
Posted in reply to Johannes Loher | Am 05.07.2016 um 17:12 schrieb Johannes Loher:
> Am 05.07.2016 um 16:39 schrieb Rene Zwanenburg:
>> On Tuesday, 5 July 2016 at 12:34:20 UTC, Johannes Loher wrote:
>>> I tried this, but it does not work correctly with slices.
>>
>> The length of a slice is a runtime value, which is why it can't be used to set static array size. What were you trying to achieve? Avoid copying the input arrays, or accepting any slice?
>>
>> In case of the first, you can put ref in front of the Args:
>> auto combineArrays(Args...)(ref Args args)
>>
>> The second case will be a bit harder to solve nicely..
>
> I would like to be able, to accept any slice. In the example in my first
> post, I need this for key[0..16] and key[16..$] (which are slices).
> Strangely enough, the solution I am leaning towards at the moment also
> uses length, but it does work for slices of static arrays (i.e. key[0..16]):
>
> template expand(alias A)
> {
> auto ref M(alias I)() @property { return A[I]; }
> mixin(q{alias expand = TypeTuple!(}
> ~ iota(A.length).map!(a => "M!" ~ a.to!string).join(",")
> ~ q{);});
> }
>
> ubyte[64] buf = [expand!sigma0,
> expand!key[0..16],
> expand!sigma1,
> expand!n,
> expand!sigma2,
> expand!key[16..$],
> expand!sigma3];
>
> I suppose this is because the length of those slices is actually known at copiletime, but it looks a bit strange to me...
>
> I was trying to write another template that takes several arrays and expands all of them:
>
> template expand(Args...)
> {
> mixin(q{alias expand = TypeTuple!(}
> ~ iota(Args.length).map!(a => "expand!(Args[" ~ a.to!string ~
> "])").join(",")
> ~ q{);});
> }
>
> It works for static arrays, but not for slices, because the template parameters are not alias parameters, so the length is then not "known" at compile time (at least that's what I think why it fails). Is there a way to specify variadic templates taking any number of alias template parameters?
>
Well, I just realized my method does not work in the case that I want to use expand on static arrays, which are returned from template functions...
|
July 05, 2016 Re: Initializing static array with contents of (static and dynamic) arrays | ||||
---|---|---|---|---|
| ||||
Posted in reply to Marc Schütz | Am 05.07.2016 um 17:22 schrieb Marc Schütz:
> auto concat(T : E[n], E, size_t n)(const E[][] args...) @nogc
> {
> size_t offset = 0;
> T result = void;
> foreach(arr; args) {
> result[offset .. offset+arr.length] = arr;
> offset += arr.length;
> }
> assert(offset == result.length);
> return result;
> }
>
> static immutable ubyte[4] sigma0 = [101, 120, 112, 97]; static immutable ubyte[4] sigma1 = [110, 100, 32, 51]; static immutable ubyte[4] sigma2 = [ 50, 45, 98, 121]; static immutable ubyte[4] sigma3 = [116, 101, 32, 107];
>
> void func(in ref ubyte[32] key, in ref ubyte[16] n) @nogc
> {
> ubyte[64] buf;
> buf[0..4] = sigma0;
> buf[4..20] = key[0..16];
> buf[20..24] = sigma1;
> buf[24..40] = n;
> buf[40..44] = sigma2;
> buf[44..60] = key[16..$];
> buf[60..64] = sigma3;
>
> auto buf2 = concat!(ubyte[64])(sigma0, key[0..16], sigma1, n,
> sigma2, key[16..$], sigma3);
>
> assert(buf == buf2);
> }
>
> void main() {
> ubyte[32] key =
> [0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1,2,3,4,5,6,7,8,9,0,1];
> ubyte[16] n = key[0..16];
> func(key, n);
> }
>
>
> Some remarks:
>
> * I added `ref` to `func`'s parameters, because the arrays are relatively large, so passing them by value might be costly (you should measure it if you care).
>
> * The `void` initialization in `concat` is an optimization that is valid only for POD types.
>
> * Returning the array is cheap because of NRVO.
This seems to be exactly what I was looking for. Thanks a lot!
|
Copyright © 1999-2021 by the D Language Foundation