74 lines
2.2 KiB
D
74 lines
2.2 KiB
D
module core.lifetime;
|
|
|
|
void copyEmplace(S, T)(ref S source, ref T target) @system
|
|
if (is(immutable S == immutable T))
|
|
{
|
|
import core.internal.traits : BaseElemOf, hasElaborateCopyConstructor, Unconst, Unqual;
|
|
|
|
// cannot have the following as simple template constraint due to nested-struct special case...
|
|
static if (!__traits(compiles, (ref S src) { T tgt = src; }))
|
|
{
|
|
alias B = BaseElemOf!T;
|
|
enum isNestedStruct = is(B == struct) && __traits(isNested, B);
|
|
static assert(isNestedStruct, "cannot copy-construct " ~ T.stringof ~ " from " ~ S.stringof);
|
|
}
|
|
|
|
void blit()
|
|
{
|
|
import core.stdc.string : memcpy;
|
|
memcpy(cast(Unqual!(T)*) &target, cast(Unqual!(T)*) &source, T.sizeof);
|
|
}
|
|
|
|
static if (is(T == struct))
|
|
{
|
|
static if (__traits(hasPostblit, T))
|
|
{
|
|
blit();
|
|
(cast() target).__xpostblit();
|
|
}
|
|
else static if (__traits(hasCopyConstructor, T))
|
|
{
|
|
// https://issues.dlang.org/show_bug.cgi?id=22766
|
|
import core.internal.lifetime : emplaceInitializer;
|
|
emplaceInitializer(*(cast(Unqual!T*)&target));
|
|
static if (__traits(isNested, T))
|
|
{
|
|
// copy context pointer
|
|
*(cast(void**) &target.tupleof[$-1]) = cast(void*) source.tupleof[$-1];
|
|
}
|
|
target.__ctor(source); // invoke copy ctor
|
|
}
|
|
else
|
|
{
|
|
blit(); // no opAssign
|
|
}
|
|
}
|
|
else static if (is(T == E[n], E, size_t n))
|
|
{
|
|
static if (hasElaborateCopyConstructor!E)
|
|
{
|
|
size_t i;
|
|
try
|
|
{
|
|
for (i = 0; i < n; i++)
|
|
copyEmplace(source[i], target[i]);
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
// destroy, in reverse order, what we've constructed so far
|
|
while (i--)
|
|
destroy(*cast(Unconst!(E)*) &target[i]);
|
|
throw e;
|
|
}
|
|
}
|
|
else // trivial copy
|
|
{
|
|
blit(); // all elements at once
|
|
}
|
|
}
|
|
else
|
|
{
|
|
*cast(Unconst!(T)*) &target = *cast(Unconst!(T)*) &source;
|
|
}
|
|
}
|