@@ -1363,6 +1363,156 @@ $(H3 $(LNAME2 implicit-copy-constructors, Implicit Copy Constructors))
1363
1363
$(P If the generated copy constructor fails to type check, it will receive the `@disable` attribute.)
1364
1364
1365
1365
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
+
1366
1516
$(H2 $(LEGACY_LNAME2 StructPostblit, struct-postblit, Struct Postblits))
1367
1517
1368
1518
$(GRAMMAR
0 commit comments