Merge pull request #4263 from wilzbach/infer_type_for_make_array_with_ranges

infer elementType for ranges in makeArray,makeSlice
This commit is contained in:
Ilya Yaroshenko 2016-07-23 08:57:42 +02:00 committed by GitHub
commit 9a00cb53e7
2 changed files with 73 additions and 6 deletions

View file

@ -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

View file

@ -643,6 +643,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,
@ -702,7 +712,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);
@ -715,12 +725,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: