Класс tuple: кортеж

Класс tuple реализует кортеж из произвольного количества элементов разных типов. В отличие от кортежей в языке Python, где элементы являются неизменяемыми, в C++ можно изменять значения элементов кортежа. Прежде чем использовать класс, необходимо в начало программы добавить инструкцию:

#include <tuple>

Создать экземпляр класса можно так:

  • объявить переменную без инициализации. Для этого перед названием переменной указывается название класса tuple, а после названия внутри угловых скобок через запятую задаются типы данных значений. Пример объявления кортежа из трех элементов без инициализации:
std::tuple<std::string, int, double> t;
std::get<0>(t) = "string";
std::get<1>(t) = 5;
std::get<2>(t) = 12.2;
std::cout << std::get<0>(t) << std::endl; // string
std::cout << std::get<1>(t) << std::endl; // 5
std::cout << std::get<2>(t) << std::endl; // 12.2
  • указав после названия переменной внутри круглых скобок значения через запятую (доступно копирование и перемещение значений):
std::tuple<std::string, int, double> t("string", 5, 12.2);
std::cout << std::get<0>(t) << std::endl; // string
std::cout << std::get<1>(t) << std::endl; // 5
std::cout << std::get<2>(t) << std::endl; // 12.2

При использовании ссылочных типов значение обязательно должно быть присвоено при инициализации:

int x = 2;
std::tuple<int&> t(x);
std::cout << std::get<0>(t) << std::endl; // 2
  • указав после названия переменной внутри круглых скобок объект класса pair:
std::pair<std::string, int> pr("string", 5);
std::tuple<std::string, int> t(pr);
std::cout << std::get<0>(t) << std::endl; // string
std::cout << std::get<1>(t) << std::endl; // 5
  • указав после названия переменной внутри круглых скобок другой объект класса pair (доступны конструкторы копирования и перемещения):
std::tuple<std::string, int> t1("string", 5);
std::tuple<std::string, int> t2(t1);
std::cout << std::get<0>(t2) << std::endl; // string
std::cout << std::get<1>(t2) << std::endl; // 5

Кроме того, можно воспользоваться шаблонной функцией make_tuple(), которая выводит типы по значениям параметров. Для создания ссылок нужно дополнительно пользоваться функциями ref() или cref(). Пример:

int x = 2;
std::tuple<char, int, int&> t = std::make_tuple('s', 5, std::ref(x));
std::cout << std::get<0>(t) << std::endl; // s
std::cout << std::get<1>(t) << std::endl; // 5
std::cout << std::get<2>(t) << std::endl; // 2

Для получения и изменения значений используется функция get(), после названия которой внутри угловых скобок указывается индекс элемента внутри кортежа, далее внутри круглых скобок передается объект класса tuple:

std::tuple<int> t(10);
std::cout << std::get<0>(t) << std::endl; // 10
std::get<0>(t) = 3;
std::cout << std::get<0>(t) << std::endl; // 3

Получить количество элементов кортежа позволяет класс tuple_size, а для получения типа элемента предназначен класс tuple_element:

std::tuple<std::string, int, int> t("string", 5, 8);
auto size = std::tuple_size<decltype(t)>::value;
std::cout << size << std::endl; // 3
std::tuple_element<1, decltype(t)>::type x = std::get<1>(t);
std::cout << x << std::endl;    // 5

Над двумя объектами класса tuple определены операции ==, !=, <, <=, > и >=. Кроме того, один объект можно присвоить другому объекту. В этом случае выполняется копирование значений или перемещение:

std::tuple<int> t1(10), t2;
t2 = t1;
std::cout << std::get<0>(t2) << std::endl; // 10

Доступно также присваивание объекта класса pair (можно копировать и перемещать):

std::pair<int, int> pr(5, 10);
std::tuple<int, int> t;
t = pr;
std::cout << std::get<0>(t) << std::endl; // 5
std::cout << std::get<1>(t) << std::endl; // 10

С помощью метода swap() можно поменять значения двух объектов местами:

std::tuple<int> t1(10), t2(5);
t1.swap(t2);
std::cout << std::get<0>(t1) << std::endl; // 5
std::cout << std::get<0>(t2) << std::endl; // 10

Распаковать кортеж и присвоить значения элементов кортежа каким-либо переменным позволяет функция tie(). Если значение какого-либо элемента кортежа не нужно, то вместо переменной следует передать объект ignore:

std::tuple<int, double> t1(10, 5.2), t2(3, 1.5);
int x = 0;
double y = 0.0;
std::tie(x, y) = t1;
std::cout << x << std::endl; // 10
std::cout << y << std::endl; // 5.2
std::tie(std::ignore, y) = t2;
std::cout << y << std::endl; // 1.5

Для объединения двух кортежей предназначена функция tuple_cat():

std::tuple<int, double> t1(10, 5.2), t2(3, 1.5);
auto t3 = std::tuple_cat(t1, t2);
std::cout << std::get<0>(t3) << std::endl; // 10
std::cout << std::get<1>(t3) << std::endl; // 5.2
std::cout << std::get<2>(t3) << std::endl; // 3
std::cout << std::get<3>(t3) << std::endl; // 1.5

С помощью функции forward_as_tuple() можно передать кортеж с временными значениями в качестве параметра в функцию. Предположим, у нас есть функция принимающая кортеж:

void print(std::tuple<int&&, double&&> t) {
   std::cout << std::get<0>(t) << ' '
             << std::get<1>(t) << std::endl;
}

Вызовем эту функцию и передадим ей значения:

print(std::forward_as_tuple(10, 1.5)); // 10 1.5

Благодаря кортежам имеется возможность возврата из функции сразу нескольких значений. Например, напишем функцию возвращающую минимальное и максимальное значения из переданных в параметрах:

// #include <cstdlib>
std::tuple<int, int> min_max(int x, int y) {
   return std::tuple<int, int>(__min(x,y), __max(x,y));
}

Вызовем эту функцию, передадим ей значения и получим результат:

int min, max;
std::tie(min, max) = min_max(10, 5);
std::cout << min << std::endl; // 5
std::cout << max << std::endl; // 10

Учебник C++ (Qt Creator и MinGW)
Учебник C++ (Qt Creator и MinGW) в формате PDF

Помощь сайту

ЮMoney (Yandex-деньги): 410011140483022

ПАО Сбербанк:
Счет: 40817810855006152256
Реквизиты банка:
Наименование: СЕВЕРО-ЗАПАДНЫЙ БАНК ПАО СБЕРБАНК
Корреспондентский счет: 30101810500000000653
БИК: 044030653
КПП: 784243001
ОКПО: 09171401
ОКОНХ: 96130
Скриншот реквизитов