On Mon, 10 Oct 2011 02:42:26 -0400, Norbert Nemec
<[email protected]> wrote:
Hi there,
after a very busy and eventful year in my personal life, I have now
finally found some time to play with D2. I am very impressed by the
progress!
One thing I noticed was that static arrays are somehow strangely limited:
It is possible to overload based on the length:
--------
void f(int[3] x) {
writeln("int[3]: ",x);
}
void f(int[4] x) {
writeln("int[4]: ",x);
}
int main(string argv[]) {
f([1,2,3]);
f([1,2,3,4]);
return 0;
}
--------
However, used as function template argument, a static array is casted to
a dynamic array:
-----------
void g(T)(T x) {
static assert (__traits(isStaticArray,T));
enum N = T.init.length;
writeln(N,": ",x);
}
int main(string argv[]) {
g([1,2,3]);
return 0;
}
------------
gives the error message:
| Error: static assert (__traits(isStaticArray,int[])) is false
| instantiated from here: g!(int[])
Without the assertion, N is defined to 0.
Further investigation shows:
-------
g!(int[3])([1,2,3]); // passes a static array
-------
int[3] x3 = [1,2,3];
g(x3); // passes a static array
-------
auto z3 = [1,2,3]; // defines z3 as dynamic array
g(y3); // passes a dynamic array
-------
So it seems, the problem is that array literals on their own turned into
dynamic arrays unless you explicitly state a static array type in some
way.
In fact, all array literals are dynamic. Examine the code for
g!(int[3])([1,2,3]) (comments added):
push 3
push 2
push 1
push 3
mov EAX,offset FLAT:_D12TypeInfo_G3i6__initZ@SYM32
push EAX
call _d_arrayliteralT@PC32 ; create dynamic array
literal
add ESP,014h
mov EBX,EAX
push dword ptr 8[EBX] ; copy the data from the
heap-allocated literal into the fixed-sized array temporary
push dword ptr 4[EBX]
push dword ptr [EBX]
call _D10testdynarr10__T1gTG3iZ1gFG3iZv@PC32 ; call g
So really, the situation is worse than you thought :)
Wouldn't it make more sense the other way around? After all, turning a
static array into a dynamic array is easy, the other way around is
prohibited by the compiler. If array literals simply had a static array
type, they could be implicitly casted to dynamic arrays when necessary
but stay static if possible.
D1 I think works that way (array and string literals are fixed-sized array
arrays). Most of the time, you don't want a static array to be passed.
Remember that fixed-size arrays are passed by *value* not by reference.
This means any large array will be fully pushed onto the stack to pass it,
not just a slice.
It also adds (most of the time unnecessarily) bloat. Think of string
literals:
foo(T)(T x)
{
writeln(x);
}
foo("hello");
foo("goodbye");
In D1, this creates *two* different instantiations of foo, one for
char[5u] and one for char[7u]. In D2 if fixed-sized array were the
default choice, both "hello" and "goodbye" would be passed by value,
meaning pushing all the data on the stack, in addition to creating the
bloat.
I do agree writing a fixed-size array literal should be easier than it is.
-Steve