Fix moveEmplace for static arrays
This commit is contained in:
parent
12fb9ff9f6
commit
e06cc5a071
@ -17,6 +17,37 @@ module tanya.algorithm.mutation;
|
|||||||
import tanya.memory.op;
|
import tanya.memory.op;
|
||||||
import tanya.meta.trait;
|
import tanya.meta.trait;
|
||||||
|
|
||||||
|
private void deinitialize(bool zero, T)(ref T value)
|
||||||
|
{
|
||||||
|
static if (is(T == U[S], U, size_t S))
|
||||||
|
{
|
||||||
|
foreach (ref e; value)
|
||||||
|
{
|
||||||
|
deinitialize!zero(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
static if (isNested!T)
|
||||||
|
{
|
||||||
|
// Don't override the context pointer.
|
||||||
|
enum size_t size = T.sizeof - (void*).sizeof;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
enum size_t size = T.sizeof;
|
||||||
|
}
|
||||||
|
static if (zero)
|
||||||
|
{
|
||||||
|
fill!0((cast(void*) &value)[0 .. size]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
copy(typeid(T).initializer()[0 .. size], (&value)[0 .. 1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Moves $(D_PARAM source) into $(D_PARAM target) assuming that
|
* Moves $(D_PARAM source) into $(D_PARAM target) assuming that
|
||||||
* $(D_PARAM target) isn't initialized.
|
* $(D_PARAM target) isn't initialized.
|
||||||
@ -48,30 +79,19 @@ in
|
|||||||
}
|
}
|
||||||
body
|
body
|
||||||
{
|
{
|
||||||
static if (is(T == struct))
|
static if (is(T == struct) || isStaticArray!T)
|
||||||
{
|
{
|
||||||
copy((&source)[0 .. 1], (&target)[0 .. 1]);
|
copy((&source)[0 .. 1], (&target)[0 .. 1]);
|
||||||
|
|
||||||
static if (hasElaborateCopyConstructor!T || hasElaborateDestructor!T)
|
static if (hasElaborateCopyConstructor!T || hasElaborateDestructor!T)
|
||||||
{
|
{
|
||||||
static if (isNested!T)
|
if (typeid(T).initializer().ptr is null)
|
||||||
{
|
{
|
||||||
// Don't override the context pointer.
|
deinitialize!true(source);
|
||||||
enum size_t size = T.sizeof - (void*).sizeof;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
enum size_t size = T.sizeof;
|
deinitialize!false(source);
|
||||||
}
|
|
||||||
|
|
||||||
const(void)[] init = typeid(T).initializer();
|
|
||||||
if (init.ptr is null)
|
|
||||||
{
|
|
||||||
fill!0((cast(void*) &source)[0 .. size]);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
copy(init[0 .. size], (&source)[0 .. 1]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -129,6 +149,28 @@ body
|
|||||||
assert(source == target);
|
assert(source == target);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Emplaces static arrays.
|
||||||
|
@nogc nothrow pure @system unittest
|
||||||
|
{
|
||||||
|
static struct S
|
||||||
|
{
|
||||||
|
size_t member;
|
||||||
|
this(size_t i) @nogc nothrow pure @safe
|
||||||
|
{
|
||||||
|
this.member = i;
|
||||||
|
}
|
||||||
|
~this() @nogc nothrow pure @safe
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
S[2] source = [ S(5), S(5) ], target = void;
|
||||||
|
moveEmplace(source, target);
|
||||||
|
assert(source[0].member == 0);
|
||||||
|
assert(target[0].member == 5);
|
||||||
|
assert(source[1].member == 0);
|
||||||
|
assert(target[1].member == 5);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Moves $(D_PARAM source) into $(D_PARAM target) assuming that
|
* Moves $(D_PARAM source) into $(D_PARAM target) assuming that
|
||||||
* $(D_PARAM target) isn't initialized.
|
* $(D_PARAM target) isn't initialized.
|
||||||
|
@ -514,7 +514,6 @@ struct Array(T)
|
|||||||
{
|
{
|
||||||
allocator.deallocate(buf);
|
allocator.deallocate(buf);
|
||||||
}
|
}
|
||||||
const T* end = this.data + this.length_;
|
|
||||||
for (T* src = this.data, dest = cast(T*) buf; src != end; ++src, ++dest)
|
for (T* src = this.data, dest = cast(T*) buf; src != end; ++src, ++dest)
|
||||||
{
|
{
|
||||||
moveEmplace(*src, *dest);
|
moveEmplace(*src, *dest);
|
||||||
@ -640,6 +639,11 @@ struct Array(T)
|
|||||||
assert(v.removeBack(3) == 0);
|
assert(v.removeBack(3) == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private @property inout(T)* end() inout
|
||||||
|
{
|
||||||
|
return this.data + this.length_;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove all elements beloning to $(D_PARAM r).
|
* Remove all elements beloning to $(D_PARAM r).
|
||||||
*
|
*
|
||||||
@ -660,12 +664,10 @@ struct Array(T)
|
|||||||
}
|
}
|
||||||
body
|
body
|
||||||
{
|
{
|
||||||
auto end = this.data + this.length;
|
auto target = r.begin;
|
||||||
auto source = Range(this, r.end, end);
|
for (auto source = r.end; source != end; ++source, ++target)
|
||||||
auto target = Range(this, r.begin, end);
|
|
||||||
for (; !source.empty; source.popFront(), target.popFront())
|
|
||||||
{
|
{
|
||||||
move(source.front, target.front);
|
move(*source, *target);
|
||||||
}
|
}
|
||||||
length = length - r.length;
|
length = length - r.length;
|
||||||
return Range(this, r.begin, this.data + length);
|
return Range(this, r.begin, this.data + length);
|
||||||
@ -696,7 +698,7 @@ struct Array(T)
|
|||||||
if (isImplicitlyConvertible!(R, T))
|
if (isImplicitlyConvertible!(R, T))
|
||||||
{
|
{
|
||||||
reserve(this.length + 1);
|
reserve(this.length + 1);
|
||||||
moveEmplace(el, *(this.data + this.length_));
|
moveEmplace(el, *end);
|
||||||
++this.length_;
|
++this.length_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user