Date: 2022-08-15
Reply-to: Justin Cooke <jgc@cems.de>
Target audience: EWG
Enhancing the break statement
Proposal: To enhance the break statement with an optional termination statement that is executed outside the scope of the broken loop. The proposed syntax is:
break statement
where statement may be a null statement (as in the classic break statement) or a non-null statement.
Motivation: Sometimes special action is required when a loop exits via a break statement. If such action is to be executed outside the broken loop’s scope, the programmer has typically needed to set a flag or use a goto. The proposed new syntax is designed to be tidier and less error-prone than either of those workarounds.
Example of usage: In this example the desired action on break is to continue with the next iteration of an enclosing loop:
Before (2 alternatives) |
After |
for (auto i : range_i) { bool broke = false; for (auto j : range_j) if (condition) normal_action_j; else { broke = true; break; }
if (broke) continue; else normal_action_i; } |
for (auto i : range_i) { for (auto j : range_j) if (condition) normal_action_j; else break continue;
normal_action_i; } |
for (auto i: range_i) { for (auto j : range_j) if (condition)normal_action_j; else goto broke;
normal_action_i;
broke: ; } |
Effect on existing code: None. Code using the proposed feature is ill-formed under C++20 and earlier standards.
Wording: (edits to N4910)
8.7 Jump statements [stmt.jump]
8.7.1 General [stmt.jump.general]
1 Jump statements unconditionally transfer control.
jump-statement:
break statement;
...
8.7.2 The break statement [stmt.break]
1 The break statement shall occur only in an iteration statement or a switch statement and causes termination of (and exit from the scope of) the smallest enclosing iteration statement or switch statement, followed by execution of the statement that follows the break keyword. The statement has a block scope (6.4.3) whose parent scope (6.4.1) is the parent scope of the enclosing iteration or switch statement. If control reaches the end of the break statement, it then passes to the statement following the terminated iteration or switch statement, if any. [Note 1: The statement following the break keyword is commonly a null statement (8.3). – end note].
[Example 1:
for (int i=0; i<m; i++) //outer loop
{ for (int j=0; j<n; j++) //inner loop
if (condition) break continue; //control passes to the increment expression of the outer loop
else …
…
}
–– end example]
A.6 Statements [gram.stmt]
jump-statement:
break statement ;
Remarks: Some of the wording is copied from 8.5.1 Selection statements. While the termination statement may be any statement, including a compound statement, some choices would render the break keyword redundant. For example, there is no semantic difference between break return; and plain return;. However, break return expression; could differ semantically from return expression; because in the latter case expression is evaluated within the loop scope. To break out of two nested levels of looping, use break break;.
Related proposals: N3587 (“For loop exit strategies”) addressed the same issue, but the proposed solution envisaged that all break statements in a loop would lead to the same termination statement. The syntax proposed here is terser and more flexible. It also supports more readable code by physically tying the termination statement to its associated break.