diff --git a/std/experimental/allocator/package.d b/std/experimental/allocator/package.d index 50eeb06d6c5..4a5e8373e92 100644 --- a/std/experimental/allocator/package.d +++ b/std/experimental/allocator/package.d @@ -737,13 +737,21 @@ unittest test(theAllocator); } +/// Ditto +Unqual!(ElementEncodingType!R)[] makeArray(Allocator, R)(auto ref Allocator alloc, R range) +if (isInputRange!R && !isInfinite!R) +{ + alias T = Unqual!(ElementEncodingType!R); + return makeArray!(T, Allocator, R)(alloc, range); +} + /// Ditto T[] makeArray(T, Allocator, R)(auto ref Allocator alloc, R range) if (isInputRange!R && !isInfinite!R) { static if (isForwardRange!R || hasLength!R) { - static if (hasLength!R) + static if (hasLength!R || isNarrowString!R) immutable length = range.length; else immutable length = range.save.walkLength; @@ -763,10 +771,18 @@ if (isInputRange!R && !isInfinite!R) alloc.deallocate(m); } - for (; !range.empty; range.popFront, ++i) + import std.conv : emplace; + static if (isNarrowString!R || isRandomAccessRange!R) { - import std.conv : emplace; - cast(void) emplace!T(result.ptr + i, range.front); + foreach (j; 0 .. range.length) + { + cast(void) emplace!T(result.ptr + i++, range[j]); + } + } + else + { + for (; !range.empty; range.popFront, ++i) + cast(void) emplace!T(result.ptr + i, range.front); } return result; @@ -826,12 +842,40 @@ unittest a = alloc.makeArray!long([5, 42]); assert(a.length == 2); assert(a == [ 5, 42]); + + // we can also infer the type + auto b = alloc.makeArray([4.0, 2.0]); + static assert(is(typeof(b) == double[])); + assert(b == [4.0, 2.0]); } import std.experimental.allocator.gc_allocator : GCAllocator; test(GCAllocator.instance); test(theAllocator); } +// infer types for strings +unittest +{ + void test(A)(auto ref A alloc) + { + auto c = alloc.makeArray("fooπ😜"); + static assert(is(typeof(c) == char[])); + assert(c == "fooπ😜"); + + auto d = alloc.makeArray("fooπ😜"d); + static assert(is(typeof(d) == dchar[])); + assert(d == "fooπ😜"); + + auto w = alloc.makeArray("fooπ😜"w); + static assert(is(typeof(w) == wchar[])); + assert(w == "fooπ😜"); + } + + import std.experimental.allocator.gc_allocator : GCAllocator; + test(GCAllocator.instance); + test(theAllocator); +} + version(unittest) { private struct ForcedInputRange diff --git a/std/experimental/ndslice/slice.d b/std/experimental/ndslice/slice.d index 52d6d58018c..9faf930b0c0 100644 --- a/std/experimental/ndslice/slice.d +++ b/std/experimental/ndslice/slice.d @@ -642,6 +642,16 @@ auto makeSlice(T, return .makeSlice!(T, replaceArrayWithPointer, Allocator)(alloc, [lengths]); } +/// ditto +auto makeSlice( + Flag!`replaceArrayWithPointer` replaceArrayWithPointer = Yes.replaceArrayWithPointer, + Allocator, + size_t N, Range)(auto ref Allocator alloc, auto ref Slice!(N, Range) slice) +{ + alias T = Unqual!(slice.DeepElemType); + return makeSlice!(T, replaceArrayWithPointer)(alloc, slice); +} + /// ditto auto makeSlice(T, Flag!`replaceArrayWithPointer` replaceArrayWithPointer = Yes.replaceArrayWithPointer, @@ -701,7 +711,7 @@ auto makeSlice(T, // makes duplicate using `makeSlice` tup.slice[0, 0, 0] = 3; - auto dup = makeSlice!int(Mallocator.instance, tup.slice); + auto dup = makeSlice(Mallocator.instance, tup.slice); assert(dup.slice == tup.slice); Mallocator.instance.dispose(tup.array); @@ -714,12 +724,25 @@ auto makeSlice(T, import std.experimental.allocator; import std.experimental.allocator.mallocator; - auto tup = makeSlice!int(Mallocator.instance, [2, 3, 4], 10); + auto tup = makeSlice(Mallocator.instance, [2, 3, 4], 10); auto slice = tup.slice; assert(slice[1, 1, 1] == 10); Mallocator.instance.dispose(tup.array); } + +@nogc unittest +{ + import std.experimental.allocator; + import std.experimental.allocator.mallocator; + + // cast to your own type + auto tup = makeSlice!double(Mallocator.instance, [2, 3, 4], 10); + auto slice = tup.slice; + assert(slice[1, 1, 1] == 10.0); + Mallocator.instance.dispose(tup.array); +} + /++ Creates a common n-dimensional array from a slice. Params: