C++ Logo

std-proposals

Advanced search

Re: [std-proposals] A draft for modern switch

From: Arthur O'Dwyer <arthur.j.odwyer_at_[hidden]>
Date: Mon, 26 May 2025 11:14:14 -0400
The main thing lacking from this entire thread has been any semblance of a
discussion of codegen.
The reason C supported `switch` from the beginning is that integers can be
put into jump tables:
    switch (i) {
      case 1: case 4: ~~
      case 2: ~~
      case 5: ~~
    }
turns into the codegen equivalent of (Godbolt
<https://godbolt.org/z/Tqn31Eqhs>)
    if (1 <= i && i <= 5) {
      Address table[] = {&&a1, &&a2, &&pass, &&a1, &&a5};
      goto *table[i];
    a1: ~~
    a2: ~~
    a5: ~~
    pass: ;
    }

It would be very cool if C++ could do that for arbitrary user-defined types
such as `std::string`... but let's start super simple, with a type where we
needn't even think about hashing yet — just a simple wrapped integer.
    class WrappedInt {
      int i_;
    public:
      constexpr WrappedInt(int i) : i_(i) {}
      std::strong_ordering operator<=>(const WrappedInt& rhs) const;
      bool operator==(const WrappedInt& rhs) const;
    };
    int main(int argc, char **argv) {
      auto w = WrappedInt(argc);
      switch (w) {
        case WrappedInt(1): case WrappedInt(4): ~~
        case WrappedInt(2): ~~
        case WrappedInt(5): ~~
      }
    }

Notice that WrappedInt doesn't have a conversion to `int`. (If it did, we
could just switch on *that*, which would make this whole feature
unnecessary.) All it has, so far, is comparison operators, which are
obviously not good enough to build a jump table in the codegen.
So (this is a probably-rhetorical question directed at @ZhaoYunshan) what
API would you have to require of the author of WrappedInt in order to make
their type "switch-able"?

Remember, the `switch` statement is *not just syntactic sugar* for an
if-else-if chain of `operator==` comparisons. That chain is slow, and we
can already write it by hand if that's what we mean. If you want `switch`
for user-defined types, you'll have to explain *how to codegen it*.
Without any idea how to codegen it, you're not doing language design —
you're just stringing words together in teletype font.

HTH,
Arthur



On Tue, May 20, 2025 at 7:38 AM Zhao YunShan via Std-Proposals <
std-proposals_at_[hidden]> wrote:

>
> In C++, the switch statement is a fundamental control-flow construct
> originally designed to work only with integer types (int, char, enum,
> etc.). However, in real-world development, programmers often need to handle
> string-based (std::string) branching logic. While the standard syntax
> does not natively support strings, well-structured design patterns can
> still leverage switch-like behavior to replace lengthy if...else if chains,
> significantly improving code readability and conciseness.
>
> #include <iostream>
> #include <string>
> int main()
> {
> std::string router;
> switch (router)
> {
> case "cpp":
> std::cout << "cpp router selected.";
> break;
> case "hpp":
> std::cout << "hpp router selected.";
> break;
> default:
> std::cout << "Unknown router type.";
> break;
> }
> return 0;
> }
>
>
> By leveraging compile-time static analysis, switch statements can be
> optimized into various efficient data structures:
>
> * Jump tables* for few cases,
> * Balanced binary search* for many branches,
> * Hash tables* where supported.
>
> This ensures optimal time complexity (*O(1)* to *O(log n)*) even with
> large branch sets.
> --
> Std-Proposals mailing list
> Std-Proposals_at_[hidden]
> https://lists.isocpp.org/mailman/listinfo.cgi/std-proposals
>

Received on 2025-05-26 15:14:32