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.
chunk
).static struct S { int i = 42; } S[2] s2 = void; emplace(&s2); assert(s2[0].i == 42 && s2[1].i == 42);
interface I {} class K : I {} K k = void; emplace(&k); assert(k is null); I i = void; emplace(&i); assert(i is null);
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 arguments args
. If T
is a class, initializes the class reference to args[0]
. This function can be @trusted
if the corresponding constructor of T
is @safe
.
chunk
).int a; int b = 42; assert(*emplace!int(&a, b) == 42);
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.
@safe
if the corresponding constructor of T
is @safe
. () @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))); }();
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.
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)
). @trusted
if the corresponding constructor of T
is @safe
. 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);
Given a raw memory area chunk
, constructs an object of non-class
type T
at that address. The constructor is passed the arguments args
, if any.
chunk
must be at least as large as T
needs and should have an alignment multiple of T
's alignment. @trusted
if the corresponding constructor of T
is @safe
. struct S { int a, b; } auto buf = new void[S.sizeof]; S s; s.a = 42; s.b = 43; auto s1 = emplace!S(buf, s); assert(s1.a == 42 && s1.b == 43);
Forwards function arguments while keeping out
, ref
, and lazy
on the parameters.
args | a parameter list or an std.meta.AliasSeq . |
AliasSeq
of args
with out
, ref
, and lazy
saved.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);
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");
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);
Moves source
into target
, 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.
T source
| Data to copy. |
T target
| Where to copy into. The destructor, if any, is invoked before the copy is performed. |
move
just performs target = source
: Object obj1 = new Object; Object obj2 = obj1; Object obj3; move(obj2, obj3); assert(obj3 is obj1); // obj2 unchanged assert(obj2 is obj1);
// 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));
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);
Similar to move
but assumes target
is uninitialized. This is more efficient because source
can be blitted over target
without destroying or initializing it first.
T source
| value to be moved into target |
T target
| uninitialized value to be filled by source |
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);
© 1999–2019 The D Language Foundation
Licensed under the Boost License 1.0.
https://dlang.org/phobos/core_lifetime.html