tgoop.com/cxx95/62
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
.