Comment #0 by bearophile_hugs — 2012-12-16T17:16:13Z
int[2] foo() {
return [1, 2].dup;
}
int[2] bar() {
int[2] __aux = [1, 2].dup;
return __aux;
}
void main() {}
DMD 2.061alpha gives:
test.d(2): Error: cannot implicitly convert expression (_adDupT(& D11TypeInfo_Ai6__initZ, [1, 2])) of type int[] to int[2u]
If possible I'd like to write code as in foo() instead of using a temporary fixed sized array as in bar(). I presume in foo() the data needs to be copied to the stack any way, so probably foo() should just be syntax sugar for bar().
The same problem happens for std.array.array():
int[2] spam() {
return [1, 2].array();
}
But it doesn't happen for an array literal:
int[2] baz() {
return [1, 2];
}
Comment #1 by Marco.Leise — 2015-11-23T16:37:03Z
This is more or less actual code of a "packet" with a header and N items. "foo" returns a reference to the data portion of the n-th item or in other words 14 bytes starting at "offset":
struct S
{
ubyte[100] m_data;
ref inout(ubyte[14]) foo(uint n) inout
{
uint offset = 2 + 14 * n;
// Not accepted:
return m_data[offset .. offset + 14];
}
}
Since D's slice syntax is [start .. stop] we end up converting the information (offset, length) to (offset, offset+length) which is possibly harder for the compiler to see through and realize the fixed length of 14 above. The most idiomatic way I came up with is:
return (cast(inout(ubyte[14][7])) m_data[2 .. 2 + 7 * (ubyte[14]).sizeof])[n];
This also works when returning structs of size N instead of ubyte[N]. That's nice when the items are representable as POD structs. Here is an example:
return (cast(inout(Pack[1])) m_data[3 .. 3 + Pack.sizeof])[0];
Note the need to use a static array of length 1 as an intermediate type before returning. The semantics of casting slices to something else should be made more consistent. As long as the compiler can deduce a static length they should implicitly cast to a static array of same type and size and ubyte[]/void[] should be explicitly castable to structs with the same rules as elsewhere (e.g. unions) in regards to pointers. I.e. The structs may not contain pointers, which is fine for data loaded from disk or received over the network.