conv.emplace: Don't call a destructor
Don't call the destructor on uninitialized elements.
This commit is contained in:
parent
d0d682ca65
commit
a04a04bb96
@ -14,6 +14,7 @@
|
|||||||
*/
|
*/
|
||||||
module tanya.conv;
|
module tanya.conv;
|
||||||
|
|
||||||
|
import tanya.algorithm.mutation;
|
||||||
import tanya.container.string;
|
import tanya.container.string;
|
||||||
import tanya.format;
|
import tanya.format;
|
||||||
import tanya.memory;
|
import tanya.memory;
|
||||||
@ -164,26 +165,12 @@ do
|
|||||||
/// 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)
|
||||||
in
|
in(memory.length >= T.sizeof)
|
||||||
{
|
out(result; memory.ptr is result)
|
||||||
assert(memory.length >= T.sizeof);
|
|
||||||
}
|
|
||||||
out (result)
|
|
||||||
{
|
|
||||||
assert(memory.ptr is result);
|
|
||||||
}
|
|
||||||
do
|
|
||||||
{
|
{
|
||||||
auto result = (() @trusted => cast(T*) memory.ptr)();
|
auto result = (() @trusted => cast(T*) memory.ptr)();
|
||||||
static if (!hasElaborateAssign!T && isAssignable!T)
|
alias trustedCopy = (ref arg) @trusted =>
|
||||||
{
|
copy((cast(void*) &arg)[0 .. T.sizeof], memory);
|
||||||
*result = T.init;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
static const T init = T.init;
|
|
||||||
copy((cast(void*) &init)[0 .. T.sizeof], memory);
|
|
||||||
}
|
|
||||||
|
|
||||||
static if (Args.length == 0)
|
static if (Args.length == 0)
|
||||||
{
|
{
|
||||||
@ -192,15 +179,25 @@ do
|
|||||||
}
|
}
|
||||||
else static if (is(typeof(result.__ctor(args))))
|
else static if (is(typeof(result.__ctor(args))))
|
||||||
{
|
{
|
||||||
|
static if (!hasElaborateAssign!T && isAssignable!T)
|
||||||
|
{
|
||||||
|
*result = T.init;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
static const T init = T.init;
|
||||||
|
trustedCopy(init);
|
||||||
|
}
|
||||||
result.__ctor(args);
|
result.__ctor(args);
|
||||||
}
|
}
|
||||||
else static if (is(typeof(T(args))))
|
else static if (Args.length == 1 && is(typeof({ T t = args[0]; })))
|
||||||
{
|
{
|
||||||
*result = T(args);
|
trustedCopy(args[0]);
|
||||||
}
|
}
|
||||||
else static if (is(typeof(*result = args))) // Args.length == 1, assignment
|
else static if (is(typeof({ T t = T(args); })))
|
||||||
{
|
{
|
||||||
*result = args;
|
auto init = T(args);
|
||||||
|
(() @trusted => moveEmplace(init, *result))();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -262,6 +259,25 @@ do
|
|||||||
static assert(is(typeof(emplace!SWithDtor(null))));
|
static assert(is(typeof(emplace!SWithDtor(null))));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Doesn't call a destructor on uninitialized elements
|
||||||
|
@nogc nothrow pure @system unittest
|
||||||
|
{
|
||||||
|
static struct WithDtor
|
||||||
|
{
|
||||||
|
private bool canBeInvoked = false;
|
||||||
|
~this() @nogc nothrow pure @safe
|
||||||
|
{
|
||||||
|
if (!this.canBeInvoked)
|
||||||
|
{
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void[WithDtor.sizeof] memory = void;
|
||||||
|
auto actual = emplace!WithDtor(memory[], WithDtor(true));
|
||||||
|
assert(actual.canBeInvoked);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Thrown if a type conversion fails.
|
* Thrown if a type conversion fails.
|
||||||
*/
|
*/
|
||||||
|
Loading…
Reference in New Issue
Block a user