Skip to content

Commit bdac92c

Browse files
committed
std.array.static_array
1 parent b26aad3 commit bdac92c

File tree

1 file changed

+228
-0
lines changed

1 file changed

+228
-0
lines changed

std/array.d

Lines changed: 228 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3891,3 +3891,231 @@ unittest
38913891
assert(appS.data == "hellow");
38923892
assert(appA.data == "hellow");
38933893
}
3894+
3895+
version(all)
3896+
{
3897+
3898+
import std.traits : CommonType, Unqual, isStaticArray;
3899+
import std.conv : emplaceRef;
3900+
3901+
// @nogc: https://issues.dlang.org/show_bug.cgi?id=18439
3902+
//nothrow @safe pure:
3903+
nothrow:
3904+
@safe:
3905+
pure:
3906+
3907+
/++
3908+
Returns a static array constructed from `a`. The type of elements can be
3909+
specified implicitly (`int[2] a = staticArray(1,2);`) or explicitly
3910+
(`float[2] a = staticArray!float(1,2)`).
3911+
D20180214T203015: The result is an rvalue, therefore uses like
3912+
`foo(staticArray(1, 2, 3))` may be inefficient because of the copies.
3913+
+/
3914+
// D20180214T185602: Workaround https://issues.dlang.org/show_bug.cgi?id=16779 (make alias to staticArray once fixed)
3915+
pragma(inline, true) U[T.length] staticArray(U = CommonType!T, T...)(T a) @nogc
3916+
{
3917+
return [a];
3918+
}
3919+
3920+
/// ditto
3921+
pragma(inline, true) U[T.length] staticArrayCast(U, T...)(T a) @nogc
3922+
{
3923+
enum n = T.length;
3924+
U[n] ret = void;
3925+
static foreach (i; 0 .. n)
3926+
{
3927+
// TODO: If any of these throws, the destructors of the already-constructed elements is not called. https://github.com/dlang/phobos/pull/4936/files#r131709329
3928+
emplaceRef!U(ret[i], cast(U) a[i]);
3929+
}
3930+
return ret;
3931+
}
3932+
3933+
///
3934+
@safe unittest
3935+
{
3936+
int val = 3;
3937+
staticArray(1, 2, val).assertSame!int([1, 2, 3]);
3938+
staticArray(1, 2.0).assertSame!double([1, 2.0]);
3939+
assert(!__traits(compiles, staticArray(1, "")));
3940+
staticArray().assertSame!void([]);
3941+
staticArray!float(1, 2).assertSame!float([1, 2]);
3942+
// see D20180214T185602
3943+
// auto a = staticArray!byte(1, 2);
3944+
staticArrayCast!byte(1, 2).assertSame!byte([1, 2]);
3945+
staticArrayCast!byte(1, 129).assertSame!byte([1, -127]);
3946+
3947+
staticArrayCast!(const(int))(1, 2).assertSame!(const(int))([1, 2]);
3948+
staticArrayCast!(immutable(int))(1, 2).assertSame!(immutable(int))([1, 2]);
3949+
staticArray([1]).assertSame!(int[])([[1]]);
3950+
version (Bug)
3951+
{
3952+
// NOTE: correctly issues a deprecation
3953+
int[] a2 = staticArray(1, 2);
3954+
}
3955+
}
3956+
3957+
/++
3958+
Returns a static array constructed from `arr`. The type of elements can be
3959+
specified implicitly (`int[2] a = [1,2].asStatic;`) or explicitly
3960+
(`float[2] a = [1,2].asStaticCast!float`).
3961+
See also D20180214T203015.
3962+
+/
3963+
pragma(inline, true) T[n] asStatic(T, size_t n)(auto ref T[n] arr) @nogc
3964+
{
3965+
return arr;
3966+
}
3967+
3968+
/// ditto
3969+
U[n] asStaticCast(U, T, size_t n)(auto ref T[n] arr) @nogc
3970+
{
3971+
U[n] ret = void;
3972+
static foreach (i; 0 .. n)
3973+
{
3974+
emplaceRef!U(ret[i], cast(U) arr[i]);
3975+
}
3976+
return ret;
3977+
}
3978+
3979+
///
3980+
@safe unittest
3981+
{
3982+
int val = 3;
3983+
static immutable gold = [1, 2, 3];
3984+
[1, 2, val].asStatic.assertSame!int([1, 2, 3]);
3985+
3986+
@nogc void checkNogc()
3987+
{
3988+
[1, 2, val].asStatic.assertSame!int(gold);
3989+
}
3990+
3991+
[1, 2, val].asStaticCast!double.assertSame!double(gold);
3992+
[1, 2, 3].asStaticCast!int.assertSame!int(gold);
3993+
3994+
[1, 2, 3].asStaticCast!(const(int)).assertSame!(const(int))(gold);
3995+
[1, 2, 3].asStaticCast!(const(double)).assertSame!(const(double))(gold);
3996+
{
3997+
const(int)[3] a2 = [1, 2, 3].asStatic;
3998+
}
3999+
4000+
[1, 129].asStaticCast!byte.assertSame!byte([1, -127]);
4001+
4002+
version (Bug)
4003+
{
4004+
// https://issues.dlang.org/show_bug.cgi?id=16779
4005+
auto a2 = [1, 2, 3].asStatic!byte;
4006+
auto a3 = [1, 2, 3].asStatic!ubyte;
4007+
4008+
// NOTE: correctly issues a deprecation
4009+
int[] a2 = [1, 2].asStatic;
4010+
}
4011+
}
4012+
4013+
/// ditto but with an range
4014+
auto asStatic(size_t n, T)(T a) @nogc
4015+
{
4016+
// TODO: ElementType vs ForeachType
4017+
alias U = typeof(a[0]);
4018+
U[n] ret = void;
4019+
size_t i;
4020+
foreach (ref ai; a)
4021+
{
4022+
emplaceRef!U(ret[i++], ai);
4023+
}
4024+
assert(i == n);
4025+
return ret;
4026+
}
4027+
4028+
/// ditto
4029+
auto asStaticCast(Un : U[n], U, size_t n, T)(T a) @nogc
4030+
{
4031+
U[n] ret = void;
4032+
size_t i;
4033+
foreach (ref ai; a)
4034+
{
4035+
emplaceRef!U(ret[i++], cast(U) ai);
4036+
}
4037+
assert(i == n);
4038+
return ret;
4039+
}
4040+
4041+
///
4042+
@safe unittest
4043+
{
4044+
import std.range;
4045+
4046+
2.iota.asStatic!2.assertSame!int([0, 1]);
4047+
2.iota.asStaticCast!(double[2]).assertSame!double([0, 1]);
4048+
2.iota.asStaticCast!(byte[2]).assertSame!byte([0, 1]);
4049+
}
4050+
4051+
///
4052+
@system unittest
4053+
{
4054+
import std.range;
4055+
4056+
assert(isThrown!Error(2.iota.asStatic!1));
4057+
assert(isThrown!Error(2.iota.asStatic!3));
4058+
}
4059+
4060+
/// ditto but with an alias
4061+
auto asStatic(alias arr)() @nogc
4062+
{
4063+
enum n = arr.length;
4064+
alias U = typeof(arr[0]);
4065+
U[n] ret = void;
4066+
static foreach (i; 0 .. n)
4067+
{
4068+
emplaceRef!U(ret[i], arr[i]);
4069+
}
4070+
return ret;
4071+
}
4072+
4073+
/// ditto
4074+
auto asStaticCast(U, alias arr)() @nogc
4075+
{
4076+
enum n = arr.length;
4077+
U[n] ret = void;
4078+
static foreach (i; 0 .. n)
4079+
{
4080+
emplaceRef!U(ret[i], cast(U) arr[i]);
4081+
}
4082+
return ret;
4083+
}
4084+
4085+
///
4086+
@safe unittest
4087+
{
4088+
import std.range;
4089+
4090+
enum a = asStatic!(2.iota);
4091+
asStatic!(2.iota).assertSame!int([0, 1]);
4092+
asStaticCast!(double, 2.iota).assertSame!double([0, 1]);
4093+
asStaticCast!(byte, 2.iota).assertSame!byte([0, 1]);
4094+
}
4095+
4096+
// Note: can't use `version (unittest)` because of https://issues.dlang.org/show_bug.cgi?id=18488
4097+
void assertSame(T, T1, T2)(T1 a, T2 b) @nogc
4098+
{
4099+
assert(is(T1 == T[T1.length]));
4100+
assert(a == b);
4101+
}
4102+
4103+
// TODO: add this to assertThrown in std.exception
4104+
bool isThrown(T : Throwable = Exception, E)(lazy E expression) @system
4105+
{
4106+
try
4107+
{
4108+
expression();
4109+
return false;
4110+
}
4111+
catch (T)
4112+
{
4113+
return true;
4114+
}
4115+
catch (Exception)
4116+
{
4117+
return false;
4118+
}
4119+
}
4120+
4121+
}

0 commit comments

Comments
 (0)