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; } } T* emplace(T)(T* chunk) @safe pure nothrow { import core.internal.lifetime : emplaceRef; emplaceRef!T(*chunk); return chunk; } template forward(args...) { import core.internal.traits : AliasSeq; template fwd(alias arg) { // by ref || lazy || const/immutable static if (__traits(isRef, arg) || __traits(isOut, arg) || __traits(isLazy, arg) || !is(typeof(move(arg)))) alias fwd = arg; // (r)value else @property auto fwd() { version (DigitalMars) { /* @@BUG 23890@@ */ } else pragma(inline, true); return move(arg); } } alias Result = AliasSeq!(); static foreach (arg; args) Result = AliasSeq!(Result, fwd!arg); static if (Result.length == 1) alias forward = Result[0]; else alias forward = Result; }