summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEugen Wissner <belka@caraus.de>2018-11-23 13:36:31 +0100
committerEugen Wissner <belka@caraus.de>2018-11-23 13:36:31 +0100
commit884dc30953c2da150322aa7e68e86f67d091ce62 (patch)
tree11cc5a1c724426a07c23b6249ffbcd616b3f407f
parente67a05138e77f39a551da78712a4da5c7d4c702b (diff)
downloadtanya-884dc30953c2da150322aa7e68e86f67d091ce62.tar.gz
Fix emplacing POD structs
-rw-r--r--source/tanya/conv.d54
1 files changed, 34 insertions, 20 deletions
diff --git a/source/tanya/conv.d b/source/tanya/conv.d
index 97fafa4..1e9c86e 100644
--- a/source/tanya/conv.d
+++ b/source/tanya/conv.d
@@ -163,6 +163,24 @@ do
return result;
}
+private void initializeOne(T)(ref void[] memory, ref T* result) @trusted
+{
+ static if (!hasElaborateAssign!T && isAssignable!T)
+ {
+ *result = T.init;
+ }
+ else static if (__VERSION__ >= 2083 // __traits(isZeroInit) available.
+ && __traits(isZeroInit, T))
+ {
+ memory.ptr[0 .. T.sizeof].fill!0;
+ }
+ else
+ {
+ static immutable T init = T.init;
+ copy((&init)[0 .. 1], memory);
+ }
+}
+
/// ditto
T* emplace(T, Args...)(void[] memory, auto ref Args args)
if (!isPolymorphicType!T && isAggregateType!T)
@@ -170,38 +188,22 @@ in(memory.length >= T.sizeof)
out(result; memory.ptr is result)
{
auto result = (() @trusted => cast(T*) memory.ptr)();
- alias trustedCopy = (ref arg) @trusted =>
- copy((cast(void*) &arg)[0 .. T.sizeof], memory);
static if (Args.length == 0)
{
static assert(is(typeof({ static T t; })),
"Default constructor is disabled");
+ initializeOne(memory, result);
}
else static if (is(typeof(result.__ctor(args))))
{
- static if (!hasElaborateAssign!T && isAssignable!T)
- {
- *result = T.init;
- }
- else
- {
- static if (__VERSION__ >= 2083 // __traits(isZeroInit) available.
- && __traits(isZeroInit, T))
- {
- (() @trusted => memory.ptr[0 .. T.sizeof])().fill!0;
- }
- else
- {
- static immutable T init = T.init;
- trustedCopy(init);
- }
- }
+ initializeOne(memory, result);
result.__ctor(args);
}
else static if (Args.length == 1 && is(typeof({ T t = args[0]; })))
{
- trustedCopy(args[0]);
+ ((ref arg) @trusted =>
+ copy((cast(void*) &arg)[0 .. T.sizeof], memory))(args[0]);
}
else static if (is(typeof({ T t = T(args); })))
{
@@ -278,6 +280,18 @@ out(result; memory.ptr is result)
assert(actual.canBeInvoked);
}
+// Initializes structs if no arguments are given
+@nogc nothrow pure @safe unittest
+{
+ static struct SEntry
+ {
+ byte content;
+ }
+ ubyte[1] mem = [3];
+
+ assert(emplace!SEntry(cast(void[]) mem[0 .. 1]).content == 0);
+}
+
/**
* Thrown if a type conversion fails.
*/