D-Programming-Language/phobos — pull request #1498 by monarchdodra (2013-08-20 13:07:44+00:00)
Title: Fixup [un|minimally]InitializedArray

Third try. I decided to concentrate on fixing/improving the simple things. It's time these get fixed

Solves:
* http://d.puremagic.com/issues/show_bug.cgi?id=9803 : minimallyInitializedArray fails past "1D" depth
* http://d.puremagic.com/issues/show_bug.cgi?id=10637 : minimallyInitializedArray: postblit on non-initialized
* http://d.puremagic.com/issues/show_bug.cgi?id=10847 : uninitializedArray accepts arguments which make it fail internally

Improvements also include these simple improvements:
* Explicitly documented as nothrow, and weakly pure.
* Works with 0 args (returns an empty slice).
* All args are pre-emptivelly changed to size_t, to avoid template over-instantiation.

Also, arguably, I think the new implementation is easier to handle, since it clearly separates 1 arg and several arg paths.

```D
auto uninitializedArray(T, I...)(I sizes) nothrow pure
if (isArray!T && allSatisfy!(isIntegral, I))
{
enum isSize_t(E) = is (E : size_t);
alias toSize_t(E) = size_t;

static assert(allSatisfy!(isSize_t, I),
format("Argument types in %s are not all convertible to size_t: %s",
I.stringof, Filter!(templateNot!(isSize_t), I).stringof));

//Eagerlly transform non-size_t into size_t to avoid template bloat
alias ST = staticMap!(toSize_t, I);

return arrayAllocImpl!(false, T, ST)(sizes);
}

auto minimallyInitializedArray(T, I...)(I sizes) nothrow pure
if (isArray!T && allSatisfy!(isIntegral, I))
{
enum isSize_t(E) = is (E : size_t);
alias toSize_t(E) = size_t;

static assert(allSatisfy!(isSize_t, I),
format("Argument types in %s are not all convertible to size_t: %s",
I.stringof, Filter!(templateNot!(isSize_t), I).stringof));

//Eagerlly transform non-size_t into size_t to avoid template bloat
alias ST = staticMap!(toSize_t, I);

return arrayAllocImpl!(true, T, ST)(sizes);
}

private auto arrayAllocImpl(bool minimallyInitialized, T, I...)(I sizes) nothrow pure
{
static assert(I.length <= nDimensions!T,
format("%s dimensions specified for a %s dimensional array.", I.length, nDimensions!T));

alias E = ElementEncodingType!T;

E[] ret;

static if (I.length != 0)
{
static assert (is(I[0] == size_t));
alias size = sizes[0];
}

static if (I.length == 1)
{
if (__ctfe)
{
static if (__traits(compiles, new E[](1)))
ret = new E[](size);
else
foreach (i; 0 .. size)
ret ~= E.init;
}
else
{
import core.stdc.string : memset;
auto ptr = cast(E*) GC.malloc(sizes[0] * E.sizeof, blockAttribute!(E));
static if (minimallyInitialized && hasIndirections!E)
memset(ptr, 0, size * E.sizeof);
ret = ptr[0 .. size];
}
}
else static if (I.length > 1)
{
ret = arrayAllocImpl!(false, E[])(size);
foreach(ref elem; ret)
elem = arrayAllocImpl!(minimallyInitialized, E)(sizes[1..$]);
}

return ret;
}
```