add moveEmplaceAll and moveEmplaceSome variant

- similar to their moveAll and moveSome counterparts
  but assume that target is an uninitialized range
This commit is contained in:
Martin Nowak 2015-08-06 11:55:22 +02:00
parent 980351894b
commit d4d301b35c

View file

@ -1257,6 +1257,55 @@ been moved.
Range2 moveAll(Range1, Range2)(Range1 src, Range2 tgt)
if (isInputRange!Range1 && isInputRange!Range2
&& is(typeof(move(src.front, tgt.front))))
{
return moveAllImpl!move(src, tgt);
}
///
pure @safe unittest
{
int[] a = [ 1, 2, 3 ];
int[] b = new int[5];
assert(moveAll(a, b) is b[3 .. $]);
assert(a == b[0 .. 3]);
assert(a == [ 1, 2, 3 ]);
}
/**
* Similar to $(LREF moveAll) but assumes all elements in `target` are
* uninitialized. Uses $(LREF moveEmplace) to move elements from
* `source` over elements from `target`.
*/
Range2 moveEmplaceAll(Range1, Range2)(Range1 src, Range2 tgt) @system
if (isInputRange!Range1 && isInputRange!Range2
&& is(typeof(moveEmplace(src.front, tgt.front))))
{
return moveAllImpl!moveEmplace(src, tgt);
}
///
pure unittest
{
static struct Foo
{
~this() pure { if (_ptr) ++*_ptr; }
int* _ptr;
}
int[3] refs = [0, 1, 2];
Foo[] src = [Foo(&refs[0]), Foo(&refs[1]), Foo(&refs[2])];
Foo[5] dst = void;
auto tail = moveEmplaceAll(src, dst[]); // move 3 value from src over dst
assert(tail.length == 2); // returns remaining uninitialized values
initializeAll(tail);
import std.algorithm.searching : all;
assert(src.all!(e => e._ptr is null));
assert(dst[0 .. 3].all!(e => e._ptr !is null));
}
private Range2 moveAllImpl(alias moveOp, Range1, Range2)(
ref Range1 src, ref Range2 tgt)
{
import std.exception : enforce;
@ -1266,7 +1315,7 @@ if (isInputRange!Range1 && isInputRange!Range2
auto toMove = src.length;
enforce(toMove <= tgt.length); // shouldn't this be an assert?
foreach (idx; 0 .. toMove)
move(src[idx], tgt[idx]);
moveOp(src[idx], tgt[idx]);
return tgt[toMove .. tgt.length];
}
else
@ -1274,22 +1323,12 @@ if (isInputRange!Range1 && isInputRange!Range2
for (; !src.empty; src.popFront(), tgt.popFront())
{
enforce(!tgt.empty); //ditto?
move(src.front, tgt.front);
moveOp(src.front, tgt.front);
}
return tgt;
}
}
///
unittest
{
int[] a = [ 1, 2, 3 ];
int[] b = new int[5];
assert(moveAll(a, b) is b[3 .. $]);
assert(a == b[0 .. 3]);
assert(a == [ 1, 2, 3 ]);
}
// moveSome
/**
For each element $(D a) in $(D src) and each element $(D b) in $(D
@ -1309,26 +1348,60 @@ Tuple!(Range1, Range2) moveSome(Range1, Range2)(Range1 src, Range2 tgt)
if (isInputRange!Range1 && isInputRange!Range2
&& is(typeof(move(src.front, tgt.front))))
{
import std.exception : enforce;
for (; !src.empty && !tgt.empty; src.popFront(), tgt.popFront())
{
enforce(!tgt.empty);
move(src.front, tgt.front);
}
return tuple(src, tgt);
return moveSomeImpl!move(src, tgt);
}
///
unittest
pure nothrow @safe @nogc unittest
{
int[] a = [ 1, 2, 3, 4, 5 ];
int[] b = new int[3];
assert(moveSome(a, b)[0] is a[3 .. $]);
int[5] a = [ 1, 2, 3, 4, 5 ];
int[3] b;
assert(moveSome(a[], b[])[0] is a[3 .. $]);
assert(a[0 .. 3] == b);
assert(a == [ 1, 2, 3, 4, 5 ]);
}
/**
* Same as $(LREF moveSome) but assumes all elements in `target` are
* uninitialized. Uses $(LREF moveEmplace) to move elements from
* `source` over elements from `target`.
*/
Tuple!(Range1, Range2) moveEmplaceSome(Range1, Range2)(Range1 src, Range2 tgt) @system
if (isInputRange!Range1 && isInputRange!Range2
&& is(typeof(move(src.front, tgt.front))))
{
return moveSomeImpl!moveEmplace(src, tgt);
}
///
pure nothrow @nogc unittest
{
static struct Foo
{
~this() pure nothrow @nogc { if (_ptr) ++*_ptr; }
int* _ptr;
}
int[4] refs = [0, 1, 2, 3];
Foo[4] src = [Foo(&refs[0]), Foo(&refs[1]), Foo(&refs[2]), Foo(&refs[3])];
Foo[3] dst = void;
auto res = moveEmplaceSome(src[], dst[]);
import std.algorithm.searching : all;
assert(src[0 .. 3].all!(e => e._ptr is null));
assert(src[3]._ptr !is null);
assert(dst[].all!(e => e._ptr !is null));
}
private Tuple!(Range1, Range2) moveSomeImpl(alias moveOp, Range1, Range2)(
ref Range1 src, ref Range2 tgt)
{
for (; !src.empty && !tgt.empty; src.popFront(), tgt.popFront())
moveOp(src.front, tgt.front);
return tuple(src, tgt);
}
// SwapStrategy
/**
Defines the swapping strategy for algorithms that need to swap