C++: Эволюция стандартов от 11 до 23
Перед собеседованиями часто задаюсь вопросом: что самое главное в каждом стандарте? Чтобы упростить себе подготовку, решил написать краткий обзор ключевых изменений в стандартах C++.
Данный пост навеян выступлениями Тимура Домлера.
C++23
Основывался на выступлении Тимура Домлера на CppCon 2022.
- deducing this
Добавляет возможность передавать ссылку на вызывающий объект (аналогself
в Python).
Заменяет CRTP (Curiously Recurring Template Pattern), позволяя писать базовые классы с реализацией методов, зависящих от полей или методов наследника, без шаблонов.
Удобная перегрузка методов по типу объекта:const
,&
,&&
.
В лямбды можно прокидывать самих себя для рекурсии. - std::expected
Унифицированный способ возвращения результата и ошибки одновременно. Содержит информацию об ошибке, если она есть (аналогResult
в Rust). - std::mdspan
Обёртка для работы с многомерными массивами. Создаём область памяти, размечаем её как многомерный массив и работаем с удобными индексами. - std::print
Инструмент для форматирования и вывода строк. Ранее был доступен толькоstd::format
.
C++20
Основывался на выступлении Тимура Домлера на CppCon 2020.
- Coroutines
Расширяют модель функций, позволяя приостанавливать и возобновлять выполнение. Отлично упрощают код с множеством обратных вызовов.
На момент выхода стандарта они ещё сырые, рекомендуется использовать с готовыми библиотеками. - Concepts
Позволяют задавать ограничения на типы в шаблонах. Ранее это делалось через SFINAE иstd::enable_if
, но выглядело сложно:template<typename T, std::enable_if_t<std::is_integral_v<T>, void*> = nullptr>
Теперь это проще и читаемее:
template <std::integral T> bool func(T arg) {} // or bool func(std::integral auto arg) {}
- Ranges
Уменьшают потребность в циклах. Позволяют комбинировать стандартные алгоритмы в ленивой манере черезviews
и оператор|
.
Вместо передачи итераторов алгоритмам можно сразу работать с контейнерами. - Modules
Замена заголовочным файлам. Работают аналогично модулям в Python.
C++17
Ключевые изменения (по личному мнению):
- std::string_view
Избавляет от копирования строк. Храним только ссылку и длину. - Structured Bindings
Декомпозиция составных объектов: пар, кортежей, массивов. Работает как в Python. - std::optional, std::variant, std::any
Удобные типы для хранения различных значений. - Fold Expressions
Упрощают работу с параметрами шаблонов, избавляя от необходимости рекурсии. - if constexpr
Делает шаблоны читаемее, удаляя ненужные ветки на этапе компиляции. В отличие от макросов, проверяет корректность кода. - if с инициализацией
Позволяет объявлять переменные прямо в условии (как вfor
). - Parallel Algorithms in std
Многопоточные версии стандартных алгоритмов. - std::filesystem
Набор инструментов для работы с файловой системой (портирован из Boost).
C++14
Этот стандарт не богат на революционные изменения:
- std::make_unique
Удобное создание умных указателей. - Placeholder type specifiers
Выведение типа возвращаемого значения (черезauto
). Полезно в шаблонах.
C++11
Этот стандарт стал основой современного C++. Без него язык уже невозможно представить.
- Move Semantics и rvalue-ссылки
Оптимизация работы с временными объектами. - auto
Автоматическое выведение типов. - lambda expressions
Просто лямды, функции внутри функций. - Brace-or-equal initializers
Списки инициализации. Использование{}
вместо()
для инициализации. - Smart pointers
Умные указатели:std::shared_ptr
,std::unique_ptr
. - constexpr
Вычисление значений на этапе компиляции. - Variadic templates + std::tuple
Шаблоны с переменным числом аргументов. На их основе созданstd::tuple
для хранения значений разных типов.