C++ Logo

std-proposals

Advanced search

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

From: Zhao YunShan <dou1984_at_[hidden]>
Date: Sat, 31 May 2025 18:18:52 +0800 (GMT+08:00)
From: Thiago Macieira <thiago_at_[hidden]>
Date: Tue, 27 May 2025 10:23:22 -0300

> 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"?

> I'm going to guess that for:
> switch (typeAexpression) {
> case typeBvalue:
>

> we need that TypeB be constexpr constructible and destructible and that there
> is a weak-ordering, constexpr operator<=>(TypeA, TypeB). An equality operator
> alone won't suffice, because then the order of case labels would matter, which
> seems ill-advised to me. Maybe the ordering can be partial, but I don't know
> for sure.


I think that `constexpr operator<=>` is an excellent choice when selecting a binary decision tree; one cannot
solely rely on `operator==`, but also needs to have a weak order.


I would also like to point out that, of course, one could also use `constexpr operator<` for comparisons here.
This approach is also applied in the equality comparison of `std::map`, where `!(a < b || a > b)` replaces `a ==
b`. For developers, this means they only need to implement `constexpr operator<`, such as in the following
implementation of an `object` class:


structobject
{
    inttag;
    std::stringdata;
    object(int_tag, std::string_data) : tag(_tag), data(_data) {}
    constexprbooloperator<(constobject&o) const
    {
        return (tag!=o.tag) ?tag<o.tag:data<o.data;
    }
};
constexprbooloperator==(const object &lh,const object &rh)
{
    return!(lh < rh || rh < lh);
}


Of course, using switch implies a statement which informs the compiler that the object being switched on is
compared to constants of the same type and performs equality comparisons. This is crucial for the compiler;
therefore, it can safely optimize the switch statement.


As for `if...else if... chains`, these weak relational optimizations may be inadvertently disrupted by developers.
It’s also possible that both operands being compared are variables, which poses significant challenges for
compiler performance optimizations.


I wrote a piece of code equivalent to `switch (string)`, using an `if...else if... chains` structure, as shown
here: https://gcc.godbolt.org/z/bf61o41M6
It appears that the compiler uses a "jump table" and does not employ a "multiway branch", which is interesting.


Additionally, I also wrote equivalent code for `switch (object)`, available here:

https://gcc.godbolt.org/z/61qhxvM16.


I believe that the above code can be further optimized using a binary decision tree, "multiway branch", or
"perfect hash table".
With the comparison of `operator<`, it becomes straightforward to sort the constants being compared, and then
implement a balanced binary tree based on the sorted sequence. This brings significant benefits for `switch`
statements with numerous case branches.
For `object`, we can standardize `operator<`. If developers have not defined their own `operator<`, it’s best to
use the default one provided by the compiler.


Regards

















Received on 2025-05-31 10:18:59