Fix emplacing POD structs

This commit is contained in:
Eugen Wissner 2018-11-23 13:36:31 +01:00
parent e67a05138e
commit 884dc30953
1 changed files with 34 additions and 20 deletions

View File

@ -163,6 +163,24 @@ do
return result; 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 /// ditto
T* emplace(T, Args...)(void[] memory, auto ref Args args) T* emplace(T, Args...)(void[] memory, auto ref Args args)
if (!isPolymorphicType!T && isAggregateType!T) if (!isPolymorphicType!T && isAggregateType!T)
@ -170,38 +188,22 @@ in(memory.length >= T.sizeof)
out(result; memory.ptr is result) out(result; memory.ptr is result)
{ {
auto result = (() @trusted => cast(T*) memory.ptr)(); 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 if (Args.length == 0)
{ {
static assert(is(typeof({ static T t; })), static assert(is(typeof({ static T t; })),
"Default constructor is disabled"); "Default constructor is disabled");
initializeOne(memory, result);
} }
else static if (is(typeof(result.__ctor(args)))) else static if (is(typeof(result.__ctor(args))))
{ {
static if (!hasElaborateAssign!T && isAssignable!T) initializeOne(memory, result);
{
*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);
}
}
result.__ctor(args); result.__ctor(args);
} }
else static if (Args.length == 1 && is(typeof({ T t = args[0]; }))) 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); }))) else static if (is(typeof({ T t = T(args); })))
{ {
@ -278,6 +280,18 @@ out(result; memory.ptr is result)
assert(actual.canBeInvoked); 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. * Thrown if a type conversion fails.
*/ */