core.lifetime
- pure nothrow @safe T*
emplace
(T)(T*chunk
); - Given a pointer
chunk
to uninitialized memory (but already typed as T), constructs an object of non-class type T at that address. If T is a class, initializes the class reference to null.Returns:A pointer to the newly constructed object (which is the same aschunk
).Examples:static struct S { int i = 42; } S[2] s2 = void; emplace(&s2); assert(s2[0].i == 42 && s2[1].i == 42);
Examples:interface I {} class K : I {} K k = void; emplace(&k); assert(k is null); I i = void; emplace(&i); assert(i is null);
- T*
emplace
(T, Args...)(T*chunk
, auto ref Argsargs
)
if (is(T == struct) || Args.length == 1); - Given a pointer
chunk
to uninitialized memory (but already typed as a non-class type T), constructs an object of type T at that address from argumentsargs
. If T is a class, initializes the class reference toargs
[0]. This function can be @trusted if the corresponding constructor of T is @safe.Returns:A pointer to the newly constructed object (which is the same aschunk
).Examples:int a; int b = 42; assert(*emplace!int(&a, b) == 42);
- T
emplace
(T, Args...)(Tchunk
, auto ref Argsargs
)
if (is(T == class)); - Given a raw memory area
chunk
(but already typed as a class type T), constructs an object of class type T at that address. The constructor is passed the arguments Args. If T is an inner class whose outer field can be used to access an instance of the enclosing class, then Args must not be empty, and the first member of it must be a valid initializer for that outer field. Correct initialization of this field is essential to access members of the outer class inside T methods.Note This function is @safe if the corresponding constructor of T is @safe.
Returns:The newly constructed object.Examples:() @safe { class SafeClass { int x; @safe this(int x) { this.x = x; } } auto buf = new void[__traits(classInstanceSize, SafeClass)]; auto support = (() @trusted => cast(SafeClass)(buf.ptr))(); auto safeClass = emplace!SafeClass(support, 5); assert(safeClass.x == 5); class UnsafeClass { int x; @system this(int x) { this.x = x; } } auto buf2 = new void[__traits(classInstanceSize, UnsafeClass)]; auto support2 = (() @trusted => cast(UnsafeClass)(buf2.ptr))(); static assert(!__traits(compiles, emplace!UnsafeClass(support2, 5))); static assert(!__traits(compiles, emplace!UnsafeClass(buf2, 5))); }();
- T
emplace
(T, Args...)(void[]chunk
, auto ref Argsargs
)
if (is(T == class)); - Given a raw memory area
chunk
, constructs an object of class type T at that address. The constructor is passed the arguments Args. If T is an inner class whose outer field can be used to access an instance of the enclosing class, then Args must not be empty, and the first member of it must be a valid initializer for that outer field. Correct initialization of this field is essential to access members of the outer class inside T methods.Preconditions
chunk
must be at least as large as T needs and should have an alignment multiple of T's alignment. (The size of a class instance is obtained by using _traits(classInstanceSize, T)).Note This function can be @trusted if the corresponding constructor of T is @safe.
Returns:The newly constructed object.Examples:static class C { int i; this(int i){this.i = i;} } auto buf = new void[__traits(classInstanceSize, C)]; auto c = emplace!C(buf, 5); assert(c.i == 5);
- T*
emplace
(T, Args...)(void[]chunk
, auto ref Argsargs
)
if (!is(T == class)); - Given a raw memory area
chunk
, constructs an object of non-class type T at that address. The constructor is passed the argumentsargs
, if any.Preconditions
chunk
must be at least as large as T needs and should have an alignment multiple of T's alignment.Note This function can be @trusted if the corresponding constructor of T is @safe.
Returns:A pointer to the newly constructed object.Examples:struct S { int a, b; } void[S.sizeof] buf = void; S s; s.a = 42; s.b = 43; auto s1 = emplace!S(buf, s); assert(s1.a == 42 && s1.b == 43);
- @system void
copyEmplace
(S, T)(ref Ssource
, ref Ttarget
)
if (is(immutable(S) == immutable(T))); - Emplaces a copy of the specified source value into uninitialized memory, i.e., simulates T
target
=source
copy-construction for cases where the target memory is already allocated and to be initialized with a copy.Parameters:S source
value to be copied into target T target
uninitialized value to be initialized with a copy of source Examples:int source = 123; int target = void; copyEmplace(source, target); assert(target == 123);
Examples:immutable int[1][1] source = [ [123] ]; immutable int[1][1] target = void; copyEmplace(source, target); assert(target[0][0] == 123);
Examples:struct S { int x; void opAssign(const scope ref S rhs) @safe pure nothrow @nogc { assert(0); } } S source = S(42); S target = void; copyEmplace(source, target); assert(target.x == 42);
- template
forward
(args...) - Forwards function arguments while keeping out, ref, and lazy on the parameters.Parameters:
args a parameter list or an std.meta.AliasSeq. Returns:An AliasSeq of args with out, ref, and lazy saved.Examples:class C { static int foo(int n) { return 1; } static int foo(ref int n) { return 2; } } // with forward int bar()(auto ref int x) { return C.foo(forward!x); } // without forward int baz()(auto ref int x) { return C.foo(x); } int i; assert(bar(1) == 1); assert(bar(i) == 2); assert(baz(1) == 2); assert(baz(i) == 2);
Examples:void foo(int n, ref string s) { s = null; foreach (i; 0 .. n) s ~= "Hello"; } // forwards all arguments which are bound to parameter tuple void bar(Args...)(auto ref Args args) { return foo(forward!args); } // forwards all arguments with swapping order void baz(Args...)(auto ref Args args) { return foo(forward!args[$/2..$], forward!args[0..$/2]); } string s; bar(1, s); assert(s == "Hello"); baz(s, 2); assert(s == "HelloHello");
Examples:struct X { int i; this(this) { ++i; } } struct Y { private X x_; this()(auto ref X x) { x_ = forward!x; } } struct Z { private const X x_; this()(auto ref X x) { x_ = forward!x; } this()(auto const ref X x) { x_ = forward!x; } } X x; const X cx; auto constX = (){ const X x; return x; }; static assert(__traits(compiles, { Y y = x; })); static assert(__traits(compiles, { Y y = X(); })); static assert(!__traits(compiles, { Y y = cx; })); static assert(!__traits(compiles, { Y y = constX(); })); static assert(__traits(compiles, { Z z = x; })); static assert(__traits(compiles, { Z z = X(); })); static assert(__traits(compiles, { Z z = cx; })); static assert(__traits(compiles, { Z z = constX(); })); Y y1 = x; // ref lvalue, copy assert(y1.x_.i == 1); Y y2 = X(); // rvalue, move assert(y2.x_.i == 0); Z z1 = x; // ref lvalue, copy assert(z1.x_.i == 1); Z z2 = X(); // rvalue, move assert(z2.x_.i == 0); Z z3 = cx; // ref const lvalue, copy assert(z3.x_.i == 1); Z z4 = constX(); // const rvalue, copy assert(z4.x_.i == 1);
- void
move
(T)(ref Tsource
, ref Ttarget
);
Tmove
(T)(return ref scope Tsource
); - Moves
source
intotarget
, via a destructive copy when necessary.If T is a struct with a destructor or postblit defined, source is reset to its .init value after it is moved into target, otherwise it is left unchanged.Preconditions If source has internal pointers that point to itself and doesn't define opPostMove, it cannot be moved, and will trigger an assertion failure.
Parameters:T source
Data to copy. T target
Where to copy into. The destructor, if any, is invoked before the copy is performed. Examples:For non-struct types,move
just performstarget
=source
:Object obj1 = new Object; Object obj2 = obj1; Object obj3; move(obj2, obj3); assert(obj3 is obj1); // obj2 unchanged assert(obj2 is obj1);
Examples:// Structs without destructors are simply copied struct S1 { int a = 1; int b = 2; } S1 s11 = { 10, 11 }; S1 s12; move(s11, s12); assert(s12 == S1(10, 11)); assert(s11 == s12); // But structs with destructors or postblits are reset to their .init value // after copying to the target. struct S2 { int a = 1; int b = 2; ~this() pure nothrow @safe @nogc { } } S2 s21 = { 3, 4 }; S2 s22; move(s21, s22); assert(s21 == S2(1, 2)); assert(s22 == S2(3, 4));
Examples:Non-copyable structs can still be moved:struct S { int a = 1; @disable this(this); ~this() pure nothrow @safe @nogc {} } S s1; s1.a = 2; S s2 = move(s1); assert(s1.a == 1); assert(s2.a == 2);
- @system void
moveEmplace
(T)(ref Tsource
, ref Ttarget
); - Similar to move but assumes
target
is uninitialized. This is more efficient becausesource
can be blitted overtarget
without destroying or initializing it first.Parameters:T source
value to be moved into target T target
uninitialized value to be filled by source Examples:static struct Foo { pure nothrow @nogc: this(int* ptr) { _ptr = ptr; } ~this() { if (_ptr) ++*_ptr; } int* _ptr; } int val; Foo foo1 = void; // uninitialized auto foo2 = Foo(&val); // initialized assert(foo2._ptr is &val); // Using `move(foo2, foo1)` would have an undefined effect because it would destroy // the uninitialized foo1. // moveEmplace directly overwrites foo1 without destroying or initializing it first. moveEmplace(foo2, foo1); assert(foo1._ptr is &val); assert(foo2._ptr is null); assert(val == 0);