Skip to content

Commit 4d0f057

Browse files
committed
document move constructor
1 parent 8501a0e commit 4d0f057

File tree

1 file changed

+150
-0
lines changed

1 file changed

+150
-0
lines changed

spec/struct.dd

+150
Original file line numberDiff line numberDiff line change
@@ -1363,6 +1363,156 @@ $(H3 $(LNAME2 implicit-copy-constructors, Implicit Copy Constructors))
13631363
$(P If the generated copy constructor fails to type check, it will receive the `@disable` attribute.)
13641364

13651365

1366+
$(H2 $(LEGACY_LNAME2 StructMoveConstructor, struct-move-constructor, Struct Move Constructors))
1367+
1368+
$(P Move constructors are used to initialize a `struct` instance from
1369+
another instance of the same type, and then the other instance is reset to its initial state.
1370+
This effects a move rather than a copy. A `struct` that defines a move constructor
1371+
is not $(RELATIVE_LINK2 POD, POD).)
1372+
1373+
$(P A constructor declaration is a move constructor declaration if it meets
1374+
the following requirements:)
1375+
1376+
$(UL
1377+
$(LI The `this` part of the declaration is preceded by an `=`, i.e. `=this` to distinguish
1378+
the move constructor from other constructors.)
1379+
1380+
$(LI It takes exactly one parameter without a
1381+
$(DDSUBLINK spec/function, function-default-args, default argument),
1382+
followed by any number of parameters with default arguments.)
1383+
1384+
$(LI Its first parameter is a $(B not)
1385+
$(DDSUBLINK spec/function, ref-params, `ref` parameter).)
1386+
1387+
$(LI The type of its first parameter is the same type as
1388+
$(DDSUBLINK spec/type, typeof, `typeof(this)`), optionally with one or more
1389+
$(DDLINK spec/const3, Type Qualifiers, type qualifiers) applied to it.)
1390+
1391+
$(LI It is not a
1392+
$(DDSUBLINK spec/template, template_ctors, template constructor declaration).)
1393+
)
1394+
1395+
---
1396+
struct A
1397+
{
1398+
=this(return scope A rhs) {} // move constructor
1399+
=this(return scope const A rhs, int b = 7) {} // move constructor with default parameter
1400+
}
1401+
---
1402+
1403+
$(P The move constructor is type checked as a normal constructor.)
1404+
1405+
$(P If a move constructor is defined, implicit calls to it will be inserted
1406+
in the following situations:)
1407+
1408+
$(OL
1409+
$(LI When an rvalue is used to initialize a variable:)
1410+
1411+
$(SPEC_RUNNABLE_EXAMPLE_RUN
1412+
---
1413+
struct A
1414+
{
1415+
int[] arr;
1416+
=this(return scope A rhs) { arr = rhs.arr; rhs.arr = null; }
1417+
}
1418+
1419+
void main()
1420+
{
1421+
A a;
1422+
a.arr = [1, 2];
1423+
1424+
A b = __rvalue(a); // move constructor gets called
1425+
b.arr[] += 1;
1426+
assert(a.arr is null); // a was reset to initial state
1427+
assert(b.arr == [2, 3]);
1428+
}
1429+
---
1430+
)
1431+
1432+
$(LI When a parameter is passed by value to a function:)
1433+
1434+
$(SPEC_RUNNABLE_EXAMPLE_COMPILE
1435+
---
1436+
struct A
1437+
{
1438+
=this(return scope A another) {}
1439+
}
1440+
1441+
void fun(A a) {}
1442+
1443+
void main()
1444+
{
1445+
A a;
1446+
fun(__rvalue(a)); // move constructor gets called
1447+
}
1448+
---
1449+
)
1450+
1451+
$(LI When a parameter is returned by value from a function and Named Returned Value Optimization (NRVO)
1452+
cannot be performed:)
1453+
1454+
$(SPEC_RUNNABLE_EXAMPLE_COMPILE
1455+
---
1456+
struct A
1457+
{
1458+
=this(return scope A another) {}
1459+
}
1460+
1461+
A fun()
1462+
{
1463+
A a;
1464+
return a; // NRVO, no move constructor call
1465+
}
1466+
1467+
A a;
1468+
A gun()
1469+
{
1470+
return __rvalue(a); // cannot perform NRVO, a moved to return value
1471+
}
1472+
1473+
void main()
1474+
{
1475+
A a = fun();
1476+
A b = gun();
1477+
}
1478+
---
1479+
)
1480+
)
1481+
1482+
$(H3 $(LNAME2 disable-move, Disabled Moving))
1483+
1484+
$(P Move constructor attributes work analogously to
1485+
$(LINK2 disable-copy, Disabled Copying).)
1486+
1487+
$(H3 $(LNAME2 move-constructor-attributes, Move Constructor Attributes))
1488+
1489+
$(P Move constructor attributes work analogously to
1490+
$(LINK2 copy-constructor-attributes, Copy Constructor Attributes).)
1491+
1492+
$(H3 $(LNAME2 implicit-move-constructors, Implicit Move Constructors))
1493+
1494+
$(P A move constructor is generated implicitly by the compiler for a `struct S`
1495+
if all of the following conditions are met:)
1496+
1497+
$(OL
1498+
$(LI `S` does not explicitly declare any move constructors;)
1499+
$(LI `S` defines at least one direct member that has a move constructor, and that
1500+
member is not overlapped (by means of `union`) with any other member.)
1501+
)
1502+
1503+
$(P If the restrictions above are met, the following move constructor is generated:)
1504+
1505+
---
1506+
=this(return scope inout(S) src) inout
1507+
{
1508+
foreach (i, ref inout field; src.tupleof)
1509+
this.tupleof[i] = field;
1510+
}
1511+
---
1512+
1513+
$(P If the generated move constructor fails to type check, it will receive the `@disable` attribute.)
1514+
1515+
13661516
$(H2 $(LEGACY_LNAME2 StructPostblit, struct-postblit, Struct Postblits))
13671517

13681518
$(GRAMMAR

0 commit comments

Comments
 (0)