move

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.

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.

  1. void move(T source, T target)
    void
    move
    (
    T
    )
    (
    ref T source
    ,
    ref T target
    )
  2. T move(T source)

Parameters

source T

Data to copy.

target T

Where to copy into. The destructor, if any, is invoked before the copy is performed.

Examples

For non-struct types, 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);
1 // Structs without destructors are simply copied
2 struct S1
3 {
4     int a = 1;
5     int b = 2;
6 }
7 S1 s11 = { 10, 11 };
8 S1 s12;
9 
10 move(s11, s12);
11 
12 assert(s12 == S1(10, 11));
13 assert(s11 == s12);
14 
15 // But structs with destructors or postblits are reset to their .init value
16 // after copying to the target.
17 struct S2
18 {
19     int a = 1;
20     int b = 2;
21 
22     ~this() pure nothrow @safe @nogc { }
23 }
24 S2 s21 = { 3, 4 };
25 S2 s22;
26 
27 move(s21, s22);
28 
29 assert(s21 == S2(1, 2));
30 assert(s22 == S2(3, 4));

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);

opPostMove will be called if defined:

struct S
{
    int a;
    void opPostMove(const ref S old)
    {
        assert(a == old.a);
        a++;
    }
}
S s1;
s1.a = 41;
S s2 = move(s1);
assert(s2.a == 42);

Meta

Suggestion Box / Bug Report