Date: Thu, 19 Dec 2024 09:45:13 -0800
> On Dec 19, 2024, at 9:07 AM, Richard Hodges via Std-Proposals <std-proposals_at_[hidden]> wrote:
>
>
>> Please, show me goto supporting the same semantics of labeled continue:
>>
>> label1: while (cond) {
>> for (….) {
>> if (x) continue label1;
>> }
>> }
>
> extern bool cond();
> extern void something(int);
>
> void test()
> {
> while (cond())
> {
> for (int i = 0 ; i < 100 ; ++i) {
> if (i == 50) goto continueat1;
> something(i);
> }
> continueat1: ;
> }
> }
>
>
That breaks if there are any objects with constructors or destructors declared after your goto. A *correct* solution based on goto, instead of the using a *not remotely new* language feature requires:
void f() {
while (cond()) { {
/* loop2: */ for (int i = 0 ; i < 100 ; ++i) { {
if (i == 50)
goto loop1_continue;
if (i == 20)
goto loop1_break;
if (i == 30)
goto loop2_continue;
if (i == 10)
goto loop2_break;
something(i);
} loop2_continue:; } loop2_break: ;
std::shared_ptr<int> example = std::make_shared<int>(1);
} loop1_continue: ; } loop1_break: ;
}
Let’s compare to the labeled continue, as available in (I guess?) c23, or: swift, rust, javascript, java, c#, zig (though the zig label reference syntax is different - `:label:` vs `label` I think):
void f() {
loop1: while (cond()) {
loop2: for (int i = 0 ; i < 100 ; ++i) {
if (i == 50)
continue loop1;
if (i == 20)
break loop1;
if (i == 30)
continue loop2;
if (i == 10)
break loop2;
something(i);
}
std::shared_ptr<int> example = std::make_shared<int>(1);
}
}
Note that it no longer relies on a naming scheme to ensure correct use, it doesn’t need manually inserted additional scopes to “make it work” or be correct. Because it’s not a hack, there’s no risk of any one accidentally making putting code before or after one of the multiple distinct labels (with compiler invisible semantics). Even better, because it does not have a whole bunch of unnecessary make-work, there’s no overhead to just labeling all your loops to be both clearer, and safe against future modifications.
—Oliver
>
>
>> Please, show me goto supporting the same semantics of labeled continue:
>>
>> label1: while (cond) {
>> for (….) {
>> if (x) continue label1;
>> }
>> }
>
> extern bool cond();
> extern void something(int);
>
> void test()
> {
> while (cond())
> {
> for (int i = 0 ; i < 100 ; ++i) {
> if (i == 50) goto continueat1;
> something(i);
> }
> continueat1: ;
> }
> }
>
>
That breaks if there are any objects with constructors or destructors declared after your goto. A *correct* solution based on goto, instead of the using a *not remotely new* language feature requires:
void f() {
while (cond()) { {
/* loop2: */ for (int i = 0 ; i < 100 ; ++i) { {
if (i == 50)
goto loop1_continue;
if (i == 20)
goto loop1_break;
if (i == 30)
goto loop2_continue;
if (i == 10)
goto loop2_break;
something(i);
} loop2_continue:; } loop2_break: ;
std::shared_ptr<int> example = std::make_shared<int>(1);
} loop1_continue: ; } loop1_break: ;
}
Let’s compare to the labeled continue, as available in (I guess?) c23, or: swift, rust, javascript, java, c#, zig (though the zig label reference syntax is different - `:label:` vs `label` I think):
void f() {
loop1: while (cond()) {
loop2: for (int i = 0 ; i < 100 ; ++i) {
if (i == 50)
continue loop1;
if (i == 20)
break loop1;
if (i == 30)
continue loop2;
if (i == 10)
break loop2;
something(i);
}
std::shared_ptr<int> example = std::make_shared<int>(1);
}
}
Note that it no longer relies on a naming scheme to ensure correct use, it doesn’t need manually inserted additional scopes to “make it work” or be correct. Because it’s not a hack, there’s no risk of any one accidentally making putting code before or after one of the multiple distinct labels (with compiler invisible semantics). Even better, because it does not have a whole bunch of unnecessary make-work, there’s no overhead to just labeling all your loops to be both clearer, and safe against future modifications.
—Oliver
Received on 2024-12-19 17:45:17