CXX95 Telegram 62
#madskillz

Простой switch для строк 🎲

В C++ в switch-выражении в case не могут находиться строки или строковые литералы.

Там могут быть только константные значения целочисленного типа или значения enum-ов (а enum это и есть целочисленный тип под прикрытием).

Такое жесткое ограничение сделано из практических соображений - switch-выражения в бинарнике могут трансформироваться в супер-оптимизированный вид с помощью branch table, когда по целочисленному значению аргумента просто вычисляется адрес кода, куда надо прыгнуть.

Понятно, что для строк branch table сделать нельзя, и эффективность switch-а не будет отличаться от кучи if-ов.

В других языках строки в switch возможны - Java 7, C# 6, но там нет упора на максимальную производительность.

Но можно сделать самописный простой "switch", чтобы упростить такой код:
    Color color = UnknownColor;
if (argv[i] == "red") {
color = Red;
} else if (argv[i] == "orange") {
color = Orange;
} else if (argv[i] == "yellow") {
color = Yellow;
} else if (argv[i] == "green") {
color = Green;
} else if (argv[i] == "violet" || argv[i] == "purple") {
color = Violet;
}
В такой:
    Color color = StringSwitch<Color>(argv[i])
.Case("red", Red)
.Case("orange", Orange)
.Case("yellow", Yellow)
.Case("green", Green)
.Cases("violet", "purple", Violet)
.Default(UnknownColor);

Реализация StringSwitch есть в llvm: StringSwitch.h

Внутри этого класса всего два поля:
1️⃣ std::string_view str - сравниваемая строка (в нашем примере argv[i])
2️⃣ std::optional<T> value - итоговое значение (в нашем случае T = Color)

При вызове метода Case, если value еще не заполнено и строка равна нужной, то value заполняется.
Есть методы EndsWith и StartsWith, которые заполнят value, если часть строки равна нужной.
Есть аналогичные case-insensitive методы, а также методы Cases для нескольких значений.
Наконец есть оператор приведения к нужному типу (в нашем случае к Color).

На мой взгляд, можно еще сделать класс LambdaSwitch, который в отличие от StringSwitch мог бы принимать лямбды, и ставить значение, если лямбда возвращает true. 😐
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8



tgoop.com/cxx95/62
Create:
Last Update:

#madskillz

Простой switch для строк 🎲

В C++ в switch-выражении в case не могут находиться строки или строковые литералы.

Там могут быть только константные значения целочисленного типа или значения enum-ов (а enum это и есть целочисленный тип под прикрытием).

Такое жесткое ограничение сделано из практических соображений - switch-выражения в бинарнике могут трансформироваться в супер-оптимизированный вид с помощью branch table, когда по целочисленному значению аргумента просто вычисляется адрес кода, куда надо прыгнуть.

Понятно, что для строк branch table сделать нельзя, и эффективность switch-а не будет отличаться от кучи if-ов.

В других языках строки в switch возможны - Java 7, C# 6, но там нет упора на максимальную производительность.

Но можно сделать самописный простой "switch", чтобы упростить такой код:

    Color color = UnknownColor;
if (argv[i] == "red") {
color = Red;
} else if (argv[i] == "orange") {
color = Orange;
} else if (argv[i] == "yellow") {
color = Yellow;
} else if (argv[i] == "green") {
color = Green;
} else if (argv[i] == "violet" || argv[i] == "purple") {
color = Violet;
}
В такой:
    Color color = StringSwitch<Color>(argv[i])
.Case("red", Red)
.Case("orange", Orange)
.Case("yellow", Yellow)
.Case("green", Green)
.Cases("violet", "purple", Violet)
.Default(UnknownColor);

Реализация StringSwitch есть в llvm: StringSwitch.h

Внутри этого класса всего два поля:
1️⃣ std::string_view str - сравниваемая строка (в нашем примере argv[i])
2️⃣ std::optional<T> value - итоговое значение (в нашем случае T = Color)

При вызове метода Case, если value еще не заполнено и строка равна нужной, то value заполняется.
Есть методы EndsWith и StartsWith, которые заполнят value, если часть строки равна нужной.
Есть аналогичные case-insensitive методы, а также методы Cases для нескольких значений.
Наконец есть оператор приведения к нужному типу (в нашем случае к Color).

На мой взгляд, можно еще сделать класс LambdaSwitch, который в отличие от StringSwitch мог бы принимать лямбды, и ставить значение, если лямбда возвращает true. 😐

BY C++95


Share with your friend now:
tgoop.com/cxx95/62

View MORE
Open in Telegram


Telegram News

Date: |

It’s easy to create a Telegram channel via desktop app or mobile app (for Android and iOS): Telegram iOS app: In the “Chats” tab, click the new message icon in the right upper corner. Select “New Channel.” During the meeting with TSE Minister Edson Fachin, Perekopsky also mentioned the TSE channel on the platform as one of the firm's key success stories. Launched as part of the company's commitments to tackle the spread of fake news in Brazil, the verified channel has attracted more than 184,000 members in less than a month. Co-founder of NFT renting protocol Rentable World emiliano.eth shared the group Tuesday morning on Twitter, calling out the "degenerate" community, or crypto obsessives that engage in high-risk trading. Content is editable within two days of publishing
from us


Telegram C++95
FROM American