Skip to content

Commit a3db0c7

Browse files
committed
Fix Issue 16745 - Add template helper for creating static arrays with the size inferred
1 parent 9939897 commit a3db0c7

File tree

1 file changed

+94
-0
lines changed

1 file changed

+94
-0
lines changed

std/array.d

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,9 @@ $(TR $(TH Function Name) $(TH Description)
6060
$(TR $(TD $(D $(LREF split)))
6161
$(TD Eagerly split a range or string into an _array.
6262
))
63+
$(TR $(TD $(D $(LREF staticArray)))
64+
$(TD Create a static array from a range.
65+
))
6366
$(TR $(TD $(D $(LREF uninitializedArray)))
6467
$(TD Returns a new _array of type $(D T) without initializing its elements.
6568
))
@@ -332,6 +335,97 @@ ElementType!String[] array(String)(String str) if (isNarrowString!String)
332335
)));
333336
}
334337

338+
339+
/**
340+
* Return a static array filled with elements from a range.
341+
*
342+
* Params:
343+
* range = a range (or aggregate with $(D opApply) function) whose elements are copied into the static array
344+
* Returns:
345+
* initialized static array
346+
*/
347+
auto staticArray(alias range)()
348+
if (isIterable!(typeof(range)) && !isInfinite!(typeof(range)))
349+
{
350+
import std.array : array;
351+
enum arr = array(range);
352+
enum sA = .staticArray(arr);
353+
return sA;
354+
}
355+
356+
///
357+
@safe @nogc nothrow unittest
358+
{
359+
import std.range;
360+
enum r = iota(3);
361+
auto sa4 = staticArray!r;
362+
static assert(sa4.length == 3);
363+
assert(sa4 == [0, 1, 2]);
364+
}
365+
366+
/**
367+
* Returns a static array filled with elements copied from a dynamic array.
368+
* In contrast to the overload that takes its source as a template alias, this takes
369+
* a it as a normal argument. This allows it to be used with runtime arrays in
370+
* situations where the length of the array is guaranteed in the function call expression
371+
* (see examples for details).
372+
*
373+
* Optionally, a target type can be provided as the first template argument, which will result
374+
* in a static array with that element type.
375+
*/
376+
T[N] staticArray(size_t N, T)(T[N] a)
377+
{
378+
return a;
379+
}
380+
381+
/// ditto
382+
TargetElemT[N] staticArray(TargetElemT, size_t N, T)(T[N] a)
383+
{
384+
Unqual!(TargetElemT)[N] result = void;
385+
386+
import std.conv : emplaceRef;
387+
foreach (i; 0 .. N)
388+
emplaceRef!TargetElemT(result[i], a[i]);
389+
390+
return (() @trusted => cast(TargetElemT[N])result)();
391+
}
392+
393+
///
394+
@safe nothrow unittest
395+
{
396+
auto sa = staticArray([1, 2]);
397+
static assert(sa.length == 2);
398+
assert(sa == [1, 2]);
399+
400+
auto sa1 = staticArray!(immutable long)(sa[0 .. 1]);
401+
static assert(is(typeof(sa1) == immutable(long)[1]));
402+
assert(sa1 == [1]);
403+
404+
int[] a = [4, 2, 3];
405+
auto sa2 = staticArray(a[0 .. 2]);
406+
static assert(sa2.length == 2);
407+
a[0] = 1;
408+
assert(sa2 == [4, 2]);
409+
410+
const size_t i = 2;
411+
auto sa3 = staticArray(a[0 .. i]);
412+
static assert(sa3.length == 2);
413+
assert(sa3 == [1, 2]);
414+
415+
version(none)
416+
auto sa4 = staticArray(a[]); // not possible
417+
}
418+
419+
///
420+
@nogc @safe nothrow unittest
421+
{
422+
int[3] a = [1, 2, 3];
423+
auto da = a[];
424+
auto sa = staticArray!(const int)(da[0 .. 3]);
425+
static assert(is(typeof(sa) == const(int)[3]));
426+
assert(sa == a);
427+
}
428+
335429
/**
336430
Returns a newly allocated associative _array from a range of key/value tuples.
337431
Params: r = An input range of tuples of keys and values.

0 commit comments

Comments
 (0)