From 884dc30953c2da150322aa7e68e86f67d091ce62 Mon Sep 17 00:00:00 2001 From: Eugen Wissner Date: Fri, 23 Nov 2018 13:36:31 +0100 Subject: [PATCH] Fix emplacing POD structs --- source/tanya/conv.d | 54 ++++++++++++++++++++++++++++----------------- 1 file 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. */