Стандарт C++23, хотя и является эволюционным шагом после C++20, приносит множество небольших, но невероятно полезных улучшений, которые делают код чище, безопаснее и выразительнее. Эти нововведения — не просто академические упражнения, а реальные инструменты для решения повседневных задач разработчика. В этой статье мы рассмотрим ключевые «лайфхаки» — практические приемы использования фич C++23, которые можно внедрять прямо сейчас в новые проекты или при рефакторинге legacy-кода.
Одной из самых ожидаемых и практичных новинок является расширение поддержки `std::optional` и `std::variant`. В C++23 появляются monadic операции для `std::optional`: `and_then`, `or_else` и `transform`. Эти операции позволяют работать с optional-значениями в функциональном стиле, избегая многословных проверок `if (opt.has_value())`.
Рассмотрим классическую проблему: получение данных из нескольких функций, каждая из которых может вернуть `std::optional`. Раньше это приводило к вложенным `if`.
```
// Допустим, у нас есть старые функции
std::optional get_user(int id);
std::optional get_profile(const User& user);
std::optional get_avatar(const Profile& profile);
// Код до C++23 (проверки вручную)
std::optional old_way(int user_id) {
auto user = get_user(user_id);
if (!user) return std::nullopt;
auto profile = get_profile(*user);
if (!profile) return std::nullopt;
return get_avatar(*profile);
}
```
С помощью `and_then` цепочка становится элегантной однострочной операцией:
```
// Код с использованием C++23 (требует поддержки компилятора)
std::optional new_way(int user_id) {
return get_user(user_id)
.and_then(get_profile) // Автоматически распаковывает User
.and_then(get_avatar); // Автоматически распаковывает Profile
}
```
Это не только короче, но и яснее выражает намерение: выполнять операции последовательно, пока каждая из них успешна.
Вторая полезная фича — `std::expected`. Это более мощная альтернатива `std::optional`, которая хранит не просто наличие/отсутствие значения, а либо результат (`T`), либо информацию об ошибке (`E`). Это идеально для функций, которые могут завершиться с ошибкой, которую нужно передать вызывающему коду.
Пример использования `std::expected` для парсинга чисел:
```
#include
#include
#include
std::expected parse_int(std::string_view sv) {
int result;
auto [ptr, ec] = std::from_chars(sv.data(), sv.data() + sv.size(), result);
if (ec != std::errc{}) {
return std::unexpected("Failed to parse integer");
}
return result;
}
void handle_input() {
auto value = parse_int("42xyz");
if (value) {
use_value(*value);
} else {
std::cerr
C++23 в действии: Практические лайфхаки для современного кода
Обзор практических приемов (лайфхаков) использования новых возможностей стандарта C++23. Статья фокусируется на монadic операциях для std::optional, типе std::expected для обработки ошибок, новых методах строк (contains, starts_with), улучшениях в Ranges (std::ranges::to) и работе с контекстом вычислений (if consteval). Приводятся конкретные примеры кода для каждого случая.
293
2
Комментарии (11)