@@ -445,7 +445,7 @@ for (int i = 0; i < 10; i++)
445
445
446
446
$(H2 $(LEGACY_LNAME2 ForeachStatement, foreach-statement, Foreach Statement))
447
447
448
- $(P A `foreach` statement loops over the contents of an aggregate .)
448
+ $(P A `foreach` statement iterates a series of values .)
449
449
450
450
$(GRAMMAR
451
451
$(GNAME AggregateForeach):
@@ -483,26 +483,48 @@ $(GNAME ForeachAggregate):
483
483
484
484
$(P
485
485
$(I ForeachAggregate) is evaluated. It must evaluate to an expression
486
- of type static array, dynamic array, associative array,
486
+ which is a static array, dynamic array, associative array,
487
487
struct, class, delegate, or sequence.
488
488
The *NoScopeNonEmptyStatement* is executed, once for each element of the
489
489
aggregate.
490
- At the start of each iteration, the variables declared by
491
- the $(I ForeachTypeList)
492
- are set to be a copy of the elements of the aggregate.
493
- If the $(I ForeachTypeAttribute) is $(D ref), it is a reference to the
494
- contents of that aggregate.
495
- If the $(I ForeachTypeAttribute) is $(D scope), the $(I ForeachType) declaration
496
- will have $(D scope) semantics.
497
490
)
498
491
$(P
499
- The aggregate must be loop invariant, meaning that
500
- elements to the aggregate cannot be added or removed from it
492
+ The number of variables declared in $(I ForeachTypeList)
493
+ depends on the kind of aggregate. The declared variables are
494
+ set at the start of each iteration.
495
+ )
496
+ $(UL
497
+ $(LI By default a single declared variable is a copy of the current element.)
498
+ $(LI If the $(I ForeachTypeAttribute) is $(D ref), that variable will
499
+ be a reference to the current element of the aggregate.)
500
+ $(LI If the $(I ForeachTypeAttribute) is $(D scope), the variable
501
+ will have $(DDSUBLINK spec/function, scope-parameters, `scope`) semantics.)
502
+ )
503
+ $(P
504
+ If not specified, the type of a $(I ForeachType) variable
505
+ can be inferred from the type of the $(I ForeachAggregate).
506
+ Note that `auto` is not a valid $(I ForeachTypeAttribute).
507
+ The two `foreach` statements below are equivalent:
508
+ )
509
+ $(SPEC_RUNNABLE_EXAMPLE_RUN
510
+ --------------
511
+ int[] arr = [1, 2, 3];
512
+
513
+ foreach (int n; arr)
514
+ writeln(n);
515
+
516
+ foreach (n; arr) // ok, n is an int
517
+ writeln(n);
518
+ --------------
519
+ )
520
+ $(P
521
+ The aggregate must be *loop invariant*, meaning that
522
+ elements cannot be added or removed from the aggregate
501
523
in the *NoScopeNonEmptyStatement*.
502
524
)
503
525
504
526
$(P A $(GLINK BreakStatement) in the body of the foreach will exit the
505
- foreach, a $(GLINK ContinueStatement) will immediately start the
527
+ loop. A $(GLINK ContinueStatement) will immediately start the
506
528
next iteration.
507
529
)
508
530
@@ -541,21 +563,6 @@ foreach (size_t i, char c; a)
541
563
order.
542
564
)
543
565
544
- $(P $(B Note:) The $(I ForeachTypeAttribute) is implicit, and when a
545
- type is not specified, it is inferred. In that case, $(D auto) is
546
- implied, and it is not necessary (and actually forbidden) to use it.
547
- )
548
-
549
- --------------
550
- int[] arr;
551
- ...
552
- foreach (n; arr) // ok, n is an int
553
- writeln(n);
554
-
555
- foreach (auto n; arr) // error, auto is redundant
556
- writeln(n);
557
- --------------
558
-
559
566
$(H3 $(LNAME2 foreach_over_arrays_of_characters, Foreach over Arrays of Characters))
560
567
561
568
$(P If the aggregate expression is a static or dynamic array of
@@ -960,7 +967,8 @@ main()
960
967
961
968
$(H3 $(LNAME2 foreach_ref_parameters, Foreach Ref Parameters))
962
969
963
- $(P $(D ref) can be used to update the original elements:
970
+ $(P $(D ref) can be used to update the original elements for some
971
+ kinds of container. Arrays support this:
964
972
)
965
973
966
974
$(SPEC_RUNNABLE_EXAMPLE_RUN
@@ -984,30 +992,28 @@ $(CONSOLE
984
992
8
985
993
9
986
994
)
987
- $(P $(D ref) can not be applied to the index values.)
988
-
989
- $(P If not specified, the $(I Type)s in the $(I ForeachType) can be
990
- inferred from
991
- the type of the $(I ForeachAggregate).
992
- )
995
+ $(P $(D ref) cannot be applied to an array index variable.)
993
996
994
997
$(H3 $(LNAME2 foreach_restrictions, Foreach Restrictions))
995
998
996
- $(P The aggregate itself must not be resized, reallocated, free'd,
999
+ $(UNDEFINED_BEHAVIOR The aggregate itself must not be resized, reallocated, free'd,
997
1000
reassigned or destructed
998
1001
while the foreach is iterating over the elements.
999
1002
)
1000
1003
1001
1004
--------------
1002
- int[] a;
1003
- int[] b;
1004
- foreach (int i ; a)
1005
+ int[] a, b ;
1006
+ ...
1007
+ foreach (int v ; a)
1005
1008
{
1006
- a = null; // error
1009
+ a ~= 4; // error
1007
1010
a.length += 10; // error
1011
+
1012
+ a = null; // error
1008
1013
a = b; // error
1009
1014
}
1010
- a = null; // ok
1015
+ a ~= 4; // OK
1016
+ a = null; // OK
1011
1017
--------------
1012
1018
1013
1019
$(H3 $(LEGACY_LNAME2 ForeachRangeStatement, foreach-range-statement, Foreach Range Statement))
@@ -1030,11 +1036,13 @@ $(GNAME ForeachRangeStatement):
1030
1036
1031
1037
$(P
1032
1038
$(I ForeachType) declares a variable with either an explicit type,
1033
- or a type inferred from $(I LwrExpression) and $(I UprExpression).
1039
+ or a common type inferred from $(I LwrExpression) and $(I UprExpression).
1034
1040
The $(I ScopeStatement) is then executed $(I n) times, where $(I n)
1035
- is the result of $(I UprExpression) - $(I LwrExpression).
1041
+ is the result of $(I UprExpression) `-` $(I LwrExpression).
1036
1042
If $(I UprExpression) is less than or equal to $(I LwrExpression),
1037
- the $(I ScopeStatement) is executed zero times.
1043
+ the $(I ScopeStatement) is not executed.)
1044
+
1045
+ $(P
1038
1046
If $(I Foreach) is $(D foreach), then the variable is set to
1039
1047
$(I LwrExpression), then incremented at the end of each iteration.
1040
1048
If $(I Foreach) is $(D foreach_reverse), then the variable is set to
0 commit comments