-
-
Notifications
You must be signed in to change notification settings - Fork 739
Fix Issue 16745 - Add template helper for creating static arrays with the size inferred #4936
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -61,6 +61,9 @@ $(TR $(TH Function Name) $(TH Description) | |
$(TR $(TD $(LREF split)) | ||
$(TD Eagerly split a range or string into an _array. | ||
)) | ||
$(TR $(TD $(LREF staticArray)) | ||
$(TD Create a static array from a range. | ||
)) | ||
$(TR $(TD $(LREF uninitializedArray)) | ||
$(TD Returns a new _array of type $(D T) without initializing its elements. | ||
)) | ||
|
@@ -354,6 +357,97 @@ 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) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. perhaps you could add |
||
{ | ||
return a; | ||
} | ||
|
||
/// ditto | ||
TargetElemT[N] staticArray(TargetElemT, size_t N, T)(T[N] a) | ||
{ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. add constraint There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. and possibly |
||
Unqual!(TargetElemT)[N] result = void; | ||
|
||
import std.conv : emplaceRef; | ||
foreach (i; 0 .. N) | ||
emplaceRef!TargetElemT(result[i], a[i]); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If any of these throws, the destructors of the already-constructed elements is not called. |
||
|
||
return (() @trusted => cast(TargetElemT[N])result)(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not clear why this should be always trusted. |
||
} | ||
|
||
/// | ||
@safe nothrow unittest | ||
{ | ||
auto sa = staticArray([1, 2]); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Examples should use the preferred notation |
||
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. | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This strikes me as an obscure feature, and the example doesn't add confidence in the usefulness of the approach. I'd think a CTFE range evaluation should work, i.e. the example above should spell like:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This doesn't work as of now. See also:
https://wiki.dlang.org/User:Quickfur/Compile-time_vs._compile-time