emplace(T)(T*chunk);chunk to uninitialized memory (but already typedasT), constructs an object of non-class typeT at thataddress. IfT is a class, initializes the class reference to null.chunk).staticstruct 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(kisnull);I i =void;emplace(&i);assert(iisnull);
emplace(T, Args...)(T*chunk, auto ref Argsargs)chunk to uninitialized memory (but already typedas a non-class typeT), constructs an object of typeT atthat address from argumentsargs. IfT is a class, initializesthe class reference toargs[0].This function can be@trusted if the corresponding constructor ofT is@safe.chunk).int a;int b = 42;assert(*emplace!int(&a, b) == 42);
emplace(T, Args...)(Tchunk, auto ref Argsargs)chunk (but already typed as a class typeT),constructs an object ofclass typeT at that address. The constructoris passed the argumentsArgs.IfT is an inner class whoseouter field can be used to access an instanceof the enclosing class, thenArgs must not be empty, and the first member of itmust be a valid initializer for thatouter field. Correct initialization ofthis field is essential to access members of the outer class insideT methods.NoteThis function is@safe if the corresponding constructor ofT is@safe.
() @safe {class SafeClass {int x; @safethis(int x) {this.x = x; } }auto buf =newvoid[__traits(classInstanceSize, SafeClass)];auto support = (() @trusted =>cast(SafeClass)(buf.ptr))();auto safeClass =emplace!SafeClass(support, 5);assert(safeClass.x == 5);class UnsafeClass {int x; @systemthis(int x) {this.x = x; } }auto buf2 =newvoid[__traits(classInstanceSize, UnsafeClass)];auto support2 = (() @trusted =>cast(UnsafeClass)(buf2.ptr))();staticassert(!__traits(compiles,emplace!UnsafeClass(support2, 5)));staticassert(!__traits(compiles,emplace!UnsafeClass(buf2, 5)));}();emplace(T, Args...)(void[]chunk, auto ref Argsargs)chunk, constructs an object ofclass typeT atthat address. The constructor is passed the argumentsArgs.IfT is an inner class whoseouter field can be used to access an instanceof the enclosing class, thenArgs must not be empty, and the first member of itmust be a valid initializer for thatouter field. Correct initialization ofthis field is essential to access members of the outer class insideT methods.Preconditionschunk must be at least as large asT needs and should have an alignmentmultiple ofT's alignment. (The size of aclass instance is obtained by using_traits(classInstanceSize, T)).
NoteThis function can be@trusted if the corresponding constructor ofT is@safe.
staticclass C{int i;this(int i){this.i = i;}}auto buf =newvoid[__traits(classInstanceSize, C)];auto c =emplace!C(buf, 5);assert(c.i == 5);
// works with -betterC too:staticextern (C++)class C{ @nogcpurenothrow @safe:int i = 3;this(int i) {assert(this.i == 3);this.i = i; }int virtualGetI() {return i; }}align(__traits(classInstanceAlignment, C))byte[__traits(classInstanceSize, C)] buffer;C c =emplace!C(buffer[], 42);assert(c.virtualGetI() == 42);
emplace(T, Args...)(void[]chunk, auto ref Argsargs)chunk, constructs an object of non-class typeT at that address. The constructor is passed theargumentsargs, if any.Preconditionschunk must be at least as largeasT needs and should have an alignment multiple ofT'salignment.
NoteThis function can be@trusted if the corresponding constructor ofT is@safe.
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);
copyEmplace(S, T)(ref Ssource, ref Ttarget)target =source copy-construction for cases where the target memory is already allocated and to be initialized with a copy.Ssource | value to be copied into target |
Ttarget | uninitialized value to be initialized with a copy of source |
intsource = 123;inttarget =void;copyEmplace(source,target);assert(target == 123);
immutableint[1][1]source = [ [123] ];immutableint[1][1]target =void;copyEmplace(source,target);assert(target[0][0] == 123);
struct S{int x;void opAssign(constscoperef S rhs) @safepurenothrow @nogc {assert(0); }}Ssource = S(42);Starget =void;copyEmplace(source,target);assert(target.x == 42);
forward(args...)| args | a parameter list or anstd.meta.AliasSeq. |
class C{staticint foo(int n) {return 1; }staticint foo(refint n) {return 2; }}// with forwardint bar()(autorefint x) {return C.foo(forward!x); }// without forwardint baz()(autorefint 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 tuplevoid bar(Args...)(autoref Args args) {return foo(forward!args); }// forwards all arguments with swapping ordervoid baz(Args...)(autoref 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()(autoref X x) { x_ =forward!x; }}struct Z{privateconst X x_;this()(autoref X x) { x_ =forward!x; }this()(autorefconst X x) { x_ =forward!x; }}X x;const X cx;auto constX = (){const X x;return x; };staticassert(__traits(compiles, { Y y = x; }));staticassert(__traits(compiles, { Y y = X(); }));staticassert(!__traits(compiles, { Y y = cx; }));staticassert(!__traits(compiles, { Y y = constX(); }));staticassert(__traits(compiles, { Z z = x; }));staticassert(__traits(compiles, { Z z = X(); }));staticassert(__traits(compiles, { Z z = cx; }));staticassert(__traits(compiles, { Z z = constX(); }));Y y1 = x;// ref lvalue, copyassert(y1.x_.i == 1);Y y2 = X();// rvalue, moveassert(y2.x_.i == 0);Z z1 = x;// ref lvalue, copyassert(z1.x_.i == 1);Z z2 = X();// rvalue, moveassert(z2.x_.i == 0);Z z3 = cx;// ref const lvalue, copyassert(z3.x_.i == 1);Z z4 = constX();// const rvalue, copyassert(z4.x_.i == 1);
move(T)(ref Tsource, ref Ttarget);move(T)(ref return scope Tsource);source intotarget, via a destructive copy when necessary.PreconditionsIf source has internal pointers that point to itself and doesn't defineopPostMove, it cannot be moved, and will trigger an assertion failure.
Tsource | Data to copy. |
Ttarget | Where to copy into. The destructor, if any, is invoked before the copy is performed. |
move just performstarget =source:Object obj1 =new Object;Object obj2 = obj1;Object obj3;move(obj2, obj3);assert(obj3is obj1);// obj2 unchangedassert(obj2is obj1);
// Structs without destructors are simply copiedstruct 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()purenothrow @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; @disablethis(this); ~this()purenothrow @safe @nogc {}}S s1;s1.a = 2;S s2 =move(s1);assert(s1.a == 1);assert(s2.a == 2);
moveEmplace(T)(ref Tsource, ref Ttarget);target is uninitialized. This is more efficient becausesource can be blitted overtarget without destroying or initializing it first.Tsource | value to be moved into target |
Ttarget | uninitialized value to be filled by source |
staticstruct Foo{purenothrow @nogc:this(int* ptr) { _ptr = ptr; } ~this() {if (_ptr) ++*_ptr; }int* _ptr;}int val;Foo foo1 =void;// uninitializedauto foo2 = Foo(&val);// initializedassert(foo2._ptris &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._ptris &val);assert(foo2._ptrisnull);assert(val == 0);
_d_delstructImpl(T)_d_delstruct(ref Tp);Tp | pointer to the value to be deleted |
_d_delstructTrace = _d_HookTraceImpl!(T, _d_delstruct, errorMessage);_d_newThrowable(T)()NoteThis function does not call the constructor ofT because that would requireforward!args, which causes errors with -dip1008. This inconvenience will be removed once -dip1008 works as intended.
_d_newclassT(T)()new C()// _d_newclass!(C)()
_d_newclassTTrace(T)(stringfile = __FILE__, intline = __LINE__, stringfuncname = __FUNCTION__);_d_newitemT(T)();struct Sz {int x = 0;}struct Si {int x = 3;}void main(){new Sz();// uses zero-initializationnew Si();// uses Si.init}