C++17 – релиз, который расширил возможности C++: в языке появились структурированные привязки, контейнеры и новые типы данных.
В версии 17 в стандартной библиотеке C++ появилось много полезных типов данных. Простейший – std::byte. Это просто единичный байт, который предназначен для работы с хранилищем данных.
std::variant
Этот тип умеет в заданное время хранить в себе значение какого-то альтернативного типа. Представьте, что поле с количеством полных лет пользователя будет реализовано как строковая дата и целочисленное значение:
std::variant взаимодействует с объектами, которые не относятся к POD-типам. В этом его отличие и преимущество перед обычными объединениями.
std::optional
std::optional является объектом, который может как хранить значение, так и быть пустым. Он будет полезен в ситуации, когда функция не возвращает значение – тогда им может стать std::optional. Использование std::optional также снижает вероятность случайного использования пустого значения.
Здесь определяется функция, которая должна преобразовать строку в целое число. С использованием std::optional при неудаче вернется ноль.
std::any
Предоставляет типобезопасный контейнер для единственного значения любого типа. Можно проверить содержимое std::any и достать из него значение, использовав std::any_cast:
Также можно применить type() при проверке содержимого, чтобы не получить исключение.
std::any поможет там, где помогал указатель void*, только будет типобезопасным. Он позволит представить значение «5» и в виде целого, и в виде строки.
Структурированные привязки – полезная новинка C++17. Они позволяют делать множественные привязки к структурированным типам, вроде массивов и кортежей. Это нужно, чтобы, например, присвоить все члены структуры независимым переменным единственным вызовом. Использование структурных привязок делает код в целом более чистым и понятным.
Кортежи
Эта структура появилась в C++11. Они аналогичны массивам и представляют собой коллекции с фиксированной длиной. Кортежи можно использовать, чтобы вернуть несколько значений функции, например так:
Этот пример вернет кортеж с двумя членами. В C++14 версии появилась возможность использовать auto с возвращаемыми типами функций, чтобы сделать вызов функции более аккуратным. Для получения значений кортежа, при этом, будет требоваться std::get:
Через std::tie можно привязать элементы кортежа к переменным, которые уже должны быть объявлены:
Благодаря этому методу можно привязывать элементы кортежа к переменным без std::get и необходимости объявлять переменные заранее:
Этот метод также позволяет получить ссылки к элементам кортежа, что невозможно с std::tie:
Массивы и структуры
Кроме кортежей, структурированные привязки можно применять к массивам и структурам:
То же с массивами:
Но в этих примерах есть недостатки:
- Структурированные привязки не применяются к части элементов, только ко всем сразу. Это обусловлено ограничениями std::tie. Если какие-то элементы не нужно привязывать, можно использовать подготовленные для этого мусорные переменные, как в примере с массивом (_dummy1, _dummy2).
- Деструктуризация будет работать только на один уровень вглубь.
К примеру, в Person имеется элемент Location:
Соберем Person и Location, используя вложенную инициализацию:
В заключение, все это работает только для классов с публичными и нестатичными данными. Основные компиляторы, вроде GCC, Clang и MSVC уже поддерживают нововведения. Подробности описаны на cppreference.