summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
authorEugen Wissner <belka@caraus.de>2017-11-01 14:27:39 +0100
committerEugen Wissner <belka@caraus.de>2017-11-01 14:27:39 +0100
commite06cc5a071fd5640beec600f7efa2446c6ed1826 (patch)
treeb02576752bd77e726863f6ccfed5ed11352d9338 /source
parent12fb9ff9f669680daa430cc65f57ac52ec702501 (diff)
downloadtanya-e06cc5a071fd5640beec600f7efa2446c6ed1826.tar.gz
Fix moveEmplace for static arrays
Diffstat (limited to 'source')
-rw-r--r--source/tanya/algorithm/mutation.d72
-rw-r--r--source/tanya/container/array.d16
2 files changed, 66 insertions, 22 deletions
diff --git a/source/tanya/algorithm/mutation.d b/source/tanya/algorithm/mutation.d
index 2543cf9..5d09379 100644
--- a/source/tanya/algorithm/mutation.d
+++ b/source/tanya/algorithm/mutation.d
@@ -17,6 +17,37 @@ module tanya.algorithm.mutation;
import tanya.memory.op;
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
* $(D_PARAM target) isn't initialized.
@@ -48,30 +79,19 @@ in
}
body
{
- static if (is(T == struct))
+ static if (is(T == struct) || isStaticArray!T)
{
copy((&source)[0 .. 1], (&target)[0 .. 1]);
static if (hasElaborateCopyConstructor!T || hasElaborateDestructor!T)
{
- static if (isNested!T)
+ if (typeid(T).initializer().ptr is null)
{
- // Don't override the context pointer.
- enum size_t size = T.sizeof - (void*).sizeof;
+ deinitialize!true(source);
}
else
{
- enum size_t size = T.sizeof;
- }
-
- 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]);
+ deinitialize!false(source);
}
}
}
@@ -129,6 +149,28 @@ body
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
* $(D_PARAM target) isn't initialized.
diff --git a/source/tanya/container/array.d b/source/tanya/container/array.d
index ee0667c..409b57b 100644
--- a/source/tanya/container/array.d
+++ b/source/tanya/container/array.d
@@ -514,7 +514,6 @@ struct Array(T)
{
allocator.deallocate(buf);
}
- const T* end = this.data + this.length_;
for (T* src = this.data, dest = cast(T*) buf; src != end; ++src, ++dest)
{
moveEmplace(*src, *dest);
@@ -640,6 +639,11 @@ struct Array(T)
assert(v.removeBack(3) == 0);
}
+ private @property inout(T)* end() inout
+ {
+ return this.data + this.length_;
+ }
+
/**
* Remove all elements beloning to $(D_PARAM r).
*
@@ -660,12 +664,10 @@ struct Array(T)
}
body
{
- auto end = this.data + this.length;
- auto source = Range(this, r.end, end);
- auto target = Range(this, r.begin, end);
- for (; !source.empty; source.popFront(), target.popFront())
+ auto target = r.begin;
+ for (auto source = r.end; source != end; ++source, ++target)
{
- move(source.front, target.front);
+ move(*source, *target);
}
length = length - r.length;
return Range(this, r.begin, this.data + length);
@@ -696,7 +698,7 @@ struct Array(T)
if (isImplicitlyConvertible!(R, T))
{
reserve(this.length + 1);
- moveEmplace(el, *(this.data + this.length_));
+ moveEmplace(el, *end);
++this.length_;
}