Skip to content

Commit f35efe4

Browse files
committed
infer ElementType for ranges in makeArray and makeSlice
1 parent 8dbad58 commit f35efe4

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
@@ -642,6 +642,16 @@ auto makeSlice(T,
642642
return .makeSlice!(T, replaceArrayWithPointer, Allocator)(alloc, [lengths]);
643643
}
644644

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

702712
// makes duplicate using `makeSlice`
703713
tup.slice[0, 0, 0] = 3;
704-
auto dup = makeSlice!int(Mallocator.instance, tup.slice);
714+
auto dup = makeSlice(Mallocator.instance, tup.slice);
705715
assert(dup.slice == tup.slice);
706716

707717
Mallocator.instance.dispose(tup.array);
@@ -714,12 +724,25 @@ auto makeSlice(T,
714724
import std.experimental.allocator;
715725
import std.experimental.allocator.mallocator;
716726

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

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

0 commit comments

Comments
 (0)