From a3db0c76379e023504d888584a06854957c97d60 Mon Sep 17 00:00:00 2001 From: John Colvin Date: Thu, 8 Dec 2016 01:28:01 +0000 Subject: [PATCH] Fix Issue 16745 - Add template helper for creating static arrays with the size inferred --- std/array.d | 94 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) diff --git a/std/array.d b/std/array.d index 21b4148f774..d3f17a54c3a 100644 --- a/std/array.d +++ b/std/array.d @@ -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. )) @@ -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.