В типе pair
всегда есть два члена, что позволяет библиотеке присвоить им имена first
(первый) и second
(второй). Для типа tuple
такое соглашение об именовании невозможно, поскольку у него нет ограничений на количество членов. В результате члены остаются безымянными. Вместо имен для обращения к членам кортежа используется библиотечный шаблон функции get
. Чтобы использовать шаблон get
, следует определить явный аргумент шаблона (см. раздел 16.2.2), задающий позицию члена, доступ к которому предстоит получить. Функция get()
получает объект кортежа и возвращает ссылку на его заданный член:
auto book = get<0>(item); //
auto cnt = get<1>(item); //
auto price = get<2>(item)/cnt; //
get<2>(item) *= 0.8; //
Значение в скобках должно быть целочисленным константным выражением (см. разделе 2.4.4). Как обычно, счет начинается с 0, а значит, первым членом будет get<0>
.
Если подробности типов в кортеже неизвестны, для выяснения количества и типов его членов можно использовать два вспомогательных шаблона класса:
typedef decltype(item) trans; //
//
size_t sz = tuple_size
//
tuple_element<1, trans>::type cnt = get<1>(item); //
Для использования шаблонов tuple_size
и tuple_element
необходимо знать тип объекта кортежа. Как обычно, проще всего определить тип объекта при помощи спецификатора decltype
(см. раздел 2.5.3). Здесь спецификатор decltype
используется для определения псевдонима для типа кортежа item
, который и используется при создании экземпляров обоих шаблонов.
Шаблон tuple_size
обладает открытой статической переменной-членом value
, содержащей количество членов в указанном кортеже. Шаблон tuple_element
получает индекс, а также тип кортежа. Он обладает открытым типом-членом type
, содержащим тип указанного члена кортежа заданного типа. Подобно функции get()
, шаблон tuple_element
ведет отсчет индексов начиная с нуля.
Операторы сравнения и равенства кортежей ведут себя подобно соответствующим операторам контейнеров (см. раздел 9.2.7). Эти операторы выполняются для членов двух кортежей, слева и справа. Сравнить два кортежа можно только при совпадении количества их членов. Кроме того, чтобы использовать операторы равенства или неравенства, должно быть допустимо сравнение каждой пары членов при помощи оператора ==
; а для использования операторов сравнения допустимым должно быть использование оператора <
. Например:
tuple
tuple
bool b = (duo == twoD); //
tuple
b = (twoD < threeD); //
tuple
b = (origin < twoD); //
<
и ==
, последовательности кортежей можно передавать алгоритмам, а также использовать кортеж как тип ключа в упорядоченном контейнере.
Упражнение 17.1. Определите кортеж, содержащий три члена типа int
, и инициализируйте их значениями 10
, 20
и 30
.
Упражнение 17.2. Определите кортеж, содержащий строку, вектор строки и пару из строки и целого числа (типы string
, vector
и pair
).
Упражнение 17.3. Перепишите программы TextQuery
из раздела 12.3 так, чтобы использовать кортеж вместо класса QueryResult
. Объясните, что на ваш взгляд лучше и почему.
17.1.2. Использование кортежей для возвращения нескольких значений
Обычно кортеж используют для возвращения из функции нескольких значений. Например, рассматриваемый книжный магазин мог бы быть одним из нескольких магазинов в сети. У каждого магазина был бы транзакционный файл, содержащий данные по каждой проданной книге. В этом случае могло бы понадобиться просмотреть все продажи данной книги по всем магазинам.