constexpr-парсинг enum в C++: без простыни из if-else
Строки из конфига, CLI и env-переменных почти всегда нужно переводить в enum. И очень быстро код зарастает однотипными ветками
Намного удобнее держать все соответствия в одной таблице. Тогда из неё можно сделать и парсинг строки в enum, и обратное преобразование enum в строку.
Сначала объявим сам enum:
Теперь добавим таблицу соответствий. Все значения лежат в одном месте, и это сразу упрощает поддержку.
После этого можно написать
Если строка неизвестна, вернём пустой результат. Это безопаснее, чем молча подставлять какое-то значение по умолчанию.
Из той же таблицы легко сделать обратное преобразование. Это удобно, когда нужно писать enum в логах, сообщениях об ошибках или конфиге.
Если значение не найдено, вернём запасной вариант.
Использование получается простым и читаемым:
Один mapping в одном месте убирает дублирование, сокращает код и делает добавление новых enum-значений намного спокойнее.
🔥 Один mapping лучше десятка
📣 C++ Ready | #практика
Строки из конфига, CLI и env-переменных почти всегда нужно переводить в enum. И очень быстро код зарастает однотипными ветками
if (s == "...").Намного удобнее держать все соответствия в одной таблице. Тогда из неё можно сделать и парсинг строки в enum, и обратное преобразование enum в строку.
Сначала объявим сам enum:
enum class log_level {
trace,
debug,
info,
error
};Теперь добавим таблицу соответствий. Все значения лежат в одном месте, и это сразу упрощает поддержку.
using namespace std::literals;
constexpr std::array mappings{
std::pair{"trace"sv, log_level::trace},
std::pair{"debug"sv, log_level::debug},
std::pair{"info"sv, log_level::info},
std::pair{"error"sv, log_level::error},
};
После этого можно написать
constexpr-парсер. Он просто проходит по таблице и ищет совпадение.constexpr std::optional<log_level>
parse_log_level(std::string_view s) {
for (auto [name, value] : mappings) {
if (name == s)
return value;
}
Если строка неизвестна, вернём пустой результат. Это безопаснее, чем молча подставлять какое-то значение по умолчанию.
return std::nullopt;
}
Из той же таблицы легко сделать обратное преобразование. Это удобно, когда нужно писать enum в логах, сообщениях об ошибках или конфиге.
constexpr std::string_view
to_string(log_level lvl) {
for (auto [name, value] : mappings) {
if (value == lvl)
return name;
}
Если значение не найдено, вернём запасной вариант.
return "unknown";
}
Использование получается простым и читаемым:
auto lvl = parse_log_level("debug")
.value_or(log_level::info);
std::cout << to_string(lvl) << '\n';Один mapping в одном месте убирает дублирование, сокращает код и делает добавление новых enum-значений намного спокойнее.
if-else веток.Please open Telegram to view this post
VIEW IN TELEGRAM
❤8👍5🔥3