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