Skip to content

Commit

Permalink
Fix Issue 16745 - Add template helper for creating static arrays with…
Browse files Browse the repository at this point in the history
… the size inferred
  • Loading branch information
John-Colvin committed Dec 8, 2016
1 parent 9939897 commit a3db0c7
Showing 1 changed file with 94 additions and 0 deletions.
94 changes: 94 additions & 0 deletions std/array.d
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,9 @@ $(TR $(TH Function Name) $(TH Description)
$(TR $(TD $(D $(LREF split)))
$(TD Eagerly split a range or string into an _array.
))
$(TR $(TD $(D $(LREF staticArray)))
$(TD Create a static array from a range.
))
$(TR $(TD $(D $(LREF uninitializedArray)))
$(TD Returns a new _array of type $(D T) without initializing its elements.
))
Expand Down Expand Up @@ -332,6 +335,97 @@ ElementType!String[] array(String)(String str) if (isNarrowString!String)
)));
}


/**
* Return a static array filled with elements from a range.
*
* Params:
* range = a range (or aggregate with $(D opApply) function) whose elements are copied into the static array
* Returns:
* initialized static array
*/
auto staticArray(alias range)()
if (isIterable!(typeof(range)) && !isInfinite!(typeof(range)))
{
import std.array : array;
enum arr = array(range);
enum sA = .staticArray(arr);
return sA;
}

///
@safe @nogc nothrow unittest
{
import std.range;
enum r = iota(3);
auto sa4 = staticArray!r;
static assert(sa4.length == 3);
assert(sa4 == [0, 1, 2]);
}

/**
* Returns a static array filled with elements copied from a dynamic array.
* In contrast to the overload that takes its source as a template alias, this takes
* a it as a normal argument. This allows it to be used with runtime arrays in
* situations where the length of the array is guaranteed in the function call expression
* (see examples for details).
*
* Optionally, a target type can be provided as the first template argument, which will result
* in a static array with that element type.
*/
T[N] staticArray(size_t N, T)(T[N] a)
{
return a;
}

/// ditto
TargetElemT[N] staticArray(TargetElemT, size_t N, T)(T[N] a)
{
Unqual!(TargetElemT)[N] result = void;

import std.conv : emplaceRef;
foreach (i; 0 .. N)
emplaceRef!TargetElemT(result[i], a[i]);

return (() @trusted => cast(TargetElemT[N])result)();
}

///
@safe nothrow unittest
{
auto sa = staticArray([1, 2]);
static assert(sa.length == 2);
assert(sa == [1, 2]);

auto sa1 = staticArray!(immutable long)(sa[0 .. 1]);
static assert(is(typeof(sa1) == immutable(long)[1]));
assert(sa1 == [1]);

int[] a = [4, 2, 3];
auto sa2 = staticArray(a[0 .. 2]);
static assert(sa2.length == 2);
a[0] = 1;
assert(sa2 == [4, 2]);

const size_t i = 2;
auto sa3 = staticArray(a[0 .. i]);
static assert(sa3.length == 2);
assert(sa3 == [1, 2]);

version(none)
auto sa4 = staticArray(a[]); // not possible
}

///
@nogc @safe nothrow unittest
{
int[3] a = [1, 2, 3];
auto da = a[];
auto sa = staticArray!(const int)(da[0 .. 3]);
static assert(is(typeof(sa) == const(int)[3]));
assert(sa == a);
}

/**
Returns a newly allocated associative _array from a range of key/value tuples.
Params: r = An input range of tuples of keys and values.
Expand Down

0 comments on commit a3db0c7

Please sign in to comment.