1. Получаем доступ к отдельным значениям std::pair
. Представьте, что у нас есть математическая функция divide_remainder
, которая принимает в качестве параметров std::pair
.
std::pair
Рассмотрим следующий способ получения доступа к отдельным значениям полученной пары.
const auto result (divide_remainder(16, 3));
std::cout << "16 / 3 is "
<< result.first << " with a remainder of "
<< result.second << '\n';
Вместо выполнения действий, показанных во фрагменте выше, мы теперь можем присвоить отдельные значения конкретным переменным с говорящими именами, что более удобочитаемо:
auto [fraction, remainder] = divide_remainder(16, 3);
std::cout << "16 / 3 is "
<< fraction << " with a remainder of "
<< remainder << '\n';
2. Структурированные привязки работают и для std::tuple
. Рассмотрим следующий пример функции, которая возвращает информацию о ценах на акции:
std::tuple
std::chrono::system_clock::time_point, unsigned>
stock_info(const std::string &name);
Присваивание результата ее работы отдельным переменным выглядит так же, как и в предыдущем примере:
const auto [name, valid_time, price] = stock_info("INTC");
3. Декомпозицию можно применять и для пользовательских структур. В качестве примера создадим следующую структуру.
struct employee {
unsigned id;
std::string name;
std::string role;
unsigned salary;
};
Теперь можно получить доступ к ее членам с помощью декомпозиции. Мы даже можем сделать это в цикле, если предполагается наличие целого вектора таких структур:
int main()
{
std::vector
/* Инициализируется в другом месте */};
for (const auto &[id, name, role, salary] : employees) {
std::cout << "Name: " << name
<< "Role: " << role
<< "Salary: " << salary << '\n';
}
}
Как это работает
Структурированные привязки всегда применяются по одному шаблону:
auto [var1, var2, ...] = <выражение пары, кортежа, структуры или массива>;
□ Количество переменных var1
, var2
... должно точно совпадать с количеством переменных в выражении, в отношении которого выполняется присваивание.
□ Элементом <выражение пары, кортежа, структуры или массива> должен быть один из следующих объектов:
• std::pair;
• std::tuple;
• структура. Все члены должны быть
• массив фиксированного размера.
□ Тип может иметь модификаторы auto
, const auto
, const auto&
и даже auto&&
.
Если в квадратных скобках вы укажете
std::tuple
auto [a, b] = tup; // Не работает
В этом примере мы пытаемся поместить кортеж с тремя переменными всего в две переменные. Компилятор незамедлительно сообщает нам об ошибке:
error: type 'std::tuple
but only 2 names were provided
auto [a, b] = tup;
Дополнительная информация
С помощью структурированных привязок вы точно так же можете получить доступ к большей части основных структур данных библиотеки STL. Рассмотрим, например, цикл, который выводит все элементы контейнера std::map
:
std::map
{"humans", 7000000000},
{"chickens", 17863376000},
{"camels", 24246291},
{"sheep", 1086881528},
/* … */
};
for (const auto &[species, count] : animal_population) {
std::cout << "There are " << count << " " << species
<< " on this planet.\n";
}