Date: Mon, 6 Jan 2025 14:00:27 -0500
On Mon, Jan 6, 2025 at 11:54 AM Ville Voutilainen <
ville.voutilainen_at_[hidden]> wrote:
> On Mon, 6 Jan 2025 at 18:20, Arthur O'Dwyer via Std-Proposals
> <std-proposals_at_[hidden]> wrote:
> > More background on the `goto` thing: C++ has supported loops, break,
> continue, and (more to the point) `switch` in constexpr evaluation mode
> since C++14. C++ has never supported `goto` in constexpr. As Richard Hodges
> said, this isn't for any deep technical reason; it's because "goto is bad".
>
> That is not correct. Implementation vendors have reported that
> supporting goto in their constexpr interpreters is a significant
> additional
> burden, and one unlike the burden required for supporting switch-case
> or break/continue.
>
Has any vendor said so publicly? Has any vendor said so in the minutes? Do
the rumors indicate *which* vendor(s) allegedly said this — like, is this
supposed to be a problem with Clang, GCC, MSVC, EDG, or someone else? (I
could imagine someone implementing constexpr goto in, say, Clang, just to
be told post-facto "Well sure it's possible in *Clang*, but it's supposed
to be hard for *another* compiler." Having the list of who-thinks-it's-hard
up front would make it easier to construct a proof that it's not.)
All I'm seeing publicly on the topic is the statements from Barry in 2017
and from Ville in 2015, which both come down on the side of "it's not
technologically hard, it's just a stylistic diktat."
P2242
<https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2242r3.html>,
which was adopted for C++23 and lifted C++14's ban on `goto`'s appearing
*lexically* within a constexpr function, sadly doesn't talk about either
(1) whether there are technical difficulties with `goto` nor (2) why `goto`
was so totally banned to begin with.
There's little *technologically* unusual about a `goto` that's not already
unusual about a `switch` (which can go to an arbitrary `case` label,
possibly in a nested scope, just like `goto`). It's just that `goto` can go
lexically backwards (a trait it shares with `break` and `continue`) as well
as lexically forwards.
Meanwhile, `continue`-with-label (the very feature C adopted in N3355
<https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3355.htm>) allows you to
actually *build* constexpr `goto` out of a `switch` state-machine. So if
some vendor does have a problem with constexpr `goto`, then that vendor
will probably also have the same problem with constexpr labeled loops — no
matter *what* syntax is adopted for them.
[UNTESTED CODE]
#define PREAMBLE(lbl) enum { INITIAL, LABEL_##lbl } state = INITIAL; \
TOP: while (true) { switch (state) { case INITIAL:;
#define GOTO(lbl) state = LABEL_##lbl; continue TOP;
#define LABEL(lbl) case LABEL_##lbl:;
#define POSTAMBLE return; }}
constexpr auto get_first_line(const std::string& string)
{
PREAMBLE(past_for)
std::string first_line{};
for (const auto character : string)
switch (character)
{
case '\n':
GOTO(past_for) // breaks from 'range-for loop'
default:
first_line += character;
break;
}
LABEL(past_for)
return first_line;
}
static_assert(get_first_line("Hello\nworld!") == "Hello");
ville.voutilainen_at_[hidden]> wrote:
> On Mon, 6 Jan 2025 at 18:20, Arthur O'Dwyer via Std-Proposals
> <std-proposals_at_[hidden]> wrote:
> > More background on the `goto` thing: C++ has supported loops, break,
> continue, and (more to the point) `switch` in constexpr evaluation mode
> since C++14. C++ has never supported `goto` in constexpr. As Richard Hodges
> said, this isn't for any deep technical reason; it's because "goto is bad".
>
> That is not correct. Implementation vendors have reported that
> supporting goto in their constexpr interpreters is a significant
> additional
> burden, and one unlike the burden required for supporting switch-case
> or break/continue.
>
Has any vendor said so publicly? Has any vendor said so in the minutes? Do
the rumors indicate *which* vendor(s) allegedly said this — like, is this
supposed to be a problem with Clang, GCC, MSVC, EDG, or someone else? (I
could imagine someone implementing constexpr goto in, say, Clang, just to
be told post-facto "Well sure it's possible in *Clang*, but it's supposed
to be hard for *another* compiler." Having the list of who-thinks-it's-hard
up front would make it easier to construct a proof that it's not.)
All I'm seeing publicly on the topic is the statements from Barry in 2017
and from Ville in 2015, which both come down on the side of "it's not
technologically hard, it's just a stylistic diktat."
P2242
<https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2021/p2242r3.html>,
which was adopted for C++23 and lifted C++14's ban on `goto`'s appearing
*lexically* within a constexpr function, sadly doesn't talk about either
(1) whether there are technical difficulties with `goto` nor (2) why `goto`
was so totally banned to begin with.
There's little *technologically* unusual about a `goto` that's not already
unusual about a `switch` (which can go to an arbitrary `case` label,
possibly in a nested scope, just like `goto`). It's just that `goto` can go
lexically backwards (a trait it shares with `break` and `continue`) as well
as lexically forwards.
Meanwhile, `continue`-with-label (the very feature C adopted in N3355
<https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3355.htm>) allows you to
actually *build* constexpr `goto` out of a `switch` state-machine. So if
some vendor does have a problem with constexpr `goto`, then that vendor
will probably also have the same problem with constexpr labeled loops — no
matter *what* syntax is adopted for them.
[UNTESTED CODE]
#define PREAMBLE(lbl) enum { INITIAL, LABEL_##lbl } state = INITIAL; \
TOP: while (true) { switch (state) { case INITIAL:;
#define GOTO(lbl) state = LABEL_##lbl; continue TOP;
#define LABEL(lbl) case LABEL_##lbl:;
#define POSTAMBLE return; }}
constexpr auto get_first_line(const std::string& string)
{
PREAMBLE(past_for)
std::string first_line{};
for (const auto character : string)
switch (character)
{
case '\n':
GOTO(past_for) // breaks from 'range-for loop'
default:
first_line += character;
break;
}
LABEL(past_for)
return first_line;
}
static_assert(get_first_line("Hello\nworld!") == "Hello");
Received on 2025-01-06 19:00:45