@@ -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 Return 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 Disabling move construction works analogously to
1485+ $(RELATIVE_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+ $(RELATIVE_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