Skip to content

Commit 9a00cb5

Browse files
authored
Merge pull request #4263 from wilzbach/infer_type_for_make_array_with_ranges
infer elementType for ranges in makeArray,makeSlice
2 parents 0bec4ee + f35efe4 commit 9a00cb5

File tree

2 files changed

+73
-6
lines changed

2 files changed

+73
-6
lines changed

std/experimental/allocator/package.d

Lines changed: 48 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -737,13 +737,21 @@ unittest
737737
test(theAllocator);
738738
}
739739

740+
/// Ditto
741+
Unqual!(ElementEncodingType!R)[] makeArray(Allocator, R)(auto ref Allocator alloc, R range)
742+
if (isInputRange!R && !isInfinite!R)
743+
{
744+
alias T = Unqual!(ElementEncodingType!R);
745+
return makeArray!(T, Allocator, R)(alloc, range);
746+
}
747+
740748
/// Ditto
741749
T[] makeArray(T, Allocator, R)(auto ref Allocator alloc, R range)
742750
if (isInputRange!R && !isInfinite!R)
743751
{
744752
static if (isForwardRange!R || hasLength!R)
745753
{
746-
static if (hasLength!R)
754+
static if (hasLength!R || isNarrowString!R)
747755
immutable length = range.length;
748756
else
749757
immutable length = range.save.walkLength;
@@ -763,10 +771,18 @@ if (isInputRange!R && !isInfinite!R)
763771
alloc.deallocate(m);
764772
}
765773

766-
for (; !range.empty; range.popFront, ++i)
774+
import std.conv : emplace;
775+
static if (isNarrowString!R || isRandomAccessRange!R)
767776
{
768-
import std.conv : emplace;
769-
cast(void) emplace!T(result.ptr + i, range.front);
777+
foreach (j; 0 .. range.length)
778+
{
779+
cast(void) emplace!T(result.ptr + i++, range[j]);
780+
}
781+
}
782+
else
783+
{
784+
for (; !range.empty; range.popFront, ++i)
785+
cast(void) emplace!T(result.ptr + i, range.front);
770786
}
771787

772788
return result;
@@ -826,12 +842,40 @@ unittest
826842
a = alloc.makeArray!long([5, 42]);
827843
assert(a.length == 2);
828844
assert(a == [ 5, 42]);
845+
846+
// we can also infer the type
847+
auto b = alloc.makeArray([4.0, 2.0]);
848+
static assert(is(typeof(b) == double[]));
849+
assert(b == [4.0, 2.0]);
829850
}
830851
import std.experimental.allocator.gc_allocator : GCAllocator;
831852
test(GCAllocator.instance);
832853
test(theAllocator);
833854
}
834855

856+
// infer types for strings
857+
unittest
858+
{
859+
void test(A)(auto ref A alloc)
860+
{
861+
auto c = alloc.makeArray("fooπ😜");
862+
static assert(is(typeof(c) == char[]));
863+
assert(c == "fooπ😜");
864+
865+
auto d = alloc.makeArray("fooπ😜"d);
866+
static assert(is(typeof(d) == dchar[]));
867+
assert(d == "fooπ😜");
868+
869+
auto w = alloc.makeArray("fooπ😜"w);
870+
static assert(is(typeof(w) == wchar[]));
871+
assert(w == "fooπ😜");
872+
}
873+
874+
import std.experimental.allocator.gc_allocator : GCAllocator;
875+
test(GCAllocator.instance);
876+
test(theAllocator);
877+
}
878+
835879
version(unittest)
836880
{
837881
private struct ForcedInputRange

std/experimental/ndslice/slice.d

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -643,6 +643,16 @@ auto makeSlice(T,
643643
return .makeSlice!(T, replaceArrayWithPointer, Allocator)(alloc, [lengths]);
644644
}
645645

646+
/// ditto
647+
auto makeSlice(
648+
Flag!`replaceArrayWithPointer` replaceArrayWithPointer = Yes.replaceArrayWithPointer,
649+
Allocator,
650+
size_t N, Range)(auto ref Allocator alloc, auto ref Slice!(N, Range) slice)
651+
{
652+
alias T = Unqual!(slice.DeepElemType);
653+
return makeSlice!(T, replaceArrayWithPointer)(alloc, slice);
654+
}
655+
646656
/// ditto
647657
auto makeSlice(T,
648658
Flag!`replaceArrayWithPointer` replaceArrayWithPointer = Yes.replaceArrayWithPointer,
@@ -702,7 +712,7 @@ auto makeSlice(T,
702712

703713
// makes duplicate using `makeSlice`
704714
tup.slice[0, 0, 0] = 3;
705-
auto dup = makeSlice!int(Mallocator.instance, tup.slice);
715+
auto dup = makeSlice(Mallocator.instance, tup.slice);
706716
assert(dup.slice == tup.slice);
707717

708718
Mallocator.instance.dispose(tup.array);
@@ -715,12 +725,25 @@ auto makeSlice(T,
715725
import std.experimental.allocator;
716726
import std.experimental.allocator.mallocator;
717727

718-
auto tup = makeSlice!int(Mallocator.instance, [2, 3, 4], 10);
728+
auto tup = makeSlice(Mallocator.instance, [2, 3, 4], 10);
719729
auto slice = tup.slice;
720730
assert(slice[1, 1, 1] == 10);
721731
Mallocator.instance.dispose(tup.array);
722732
}
723733

734+
735+
@nogc unittest
736+
{
737+
import std.experimental.allocator;
738+
import std.experimental.allocator.mallocator;
739+
740+
// cast to your own type
741+
auto tup = makeSlice!double(Mallocator.instance, [2, 3, 4], 10);
742+
auto slice = tup.slice;
743+
assert(slice[1, 1, 1] == 10.0);
744+
Mallocator.instance.dispose(tup.array);
745+
}
746+
724747
/++
725748
Creates a common n-dimensional array from a slice.
726749
Params:

0 commit comments

Comments
 (0)