11. Последний шаг состоит в том, чтобы распаковать все значения из входных кортежей a
b
и поместить их в z
. Вызов apply(z,a)
помещает все значения из a
в набор параметров xs
, а вызов apply(...,b)
помещает все значения b
в набор параметров ys
. Полученный кортеж представляет собой остальные сгруппированные кортежи, которые мы и возвращаем вызывающей стороне: return apply(apply(z, a), b);
}
12. Мы написали довольно много строк кода для вспомогательных функций. Теперь воспользуемся ими. Сначала создадим произвольные кортежи. student
student_desc
включает строки, которые описывают значение этих полей, в форме, доступной человеку. std::make_tuple
— приятный помощник, поскольку определяет тип всех аргументов и создает подходящий тип кортежа:int main()
{
auto student_desc (make_tuple("ID", "Name", "GPA"));
auto student (make_tuple(123456, "John Doe", 3.7));
13. Выведем на экран все, чем располагаем. Сделать это очень легко, поскольку мы только что реализовали соответствующую перегруженную версию оператора <<
cout << student_desc << '\n'
<< student << '\n';
14. Кроме того, можем сгруппировать оба кортежа динамически с помощью std::tuple_cat
cout << tuple_cat(student_desc, student) << '\n';
15. Мы можем создать и новый
zip
, и вывести его на экран: auto zipped (zip(student_desc, student));
cout << zipped << '\n';
16. Не будем забывать и о функции sum_min_max_avg
auto numbers = {0.0, 1.0, 2.0, 3.0, 4.0};
cout << zip(
make_tuple("Sum", "Minimum", "Maximum", "Average"),
sum_min_max_avg(numbers))
<< '\n';
}
17. Компиляция и запуск программы дадут следующий результат. Первые две строки представляют отдельные кортежи student
student_desc
. Третья строка — это комбинация кортежей, которую мы получили с помощью вызова tuple_cat
. Четвертая содержит сгруппированный кортеж для студента. В последней строке видим сумму, а также минимальное, максимальное и среднее значения для созданного нами списка чисел. Благодаря группировке очень легко понять смысл каждого значения.$ ./tuple
(ID, Name, GPA)
(123456, John Doe, 3.7)
(ID, Name, GPA, 123456, John Doe, 3.7)
(ID, 123456, Name, John Doe, GPA, 3.7)
(Sum, 10, Minimum, 0, Maximum, 4, Average, 2)
Как это работает
Отдельные фрагменты кода, представленные в этом разделе, довольно сложны. Мы написали реализацию operator<<
sum_min_max_avg
, возвращающую кортеж. Еще одним сложным моментом является функция zip
.Самой простой частью была функция sum_min_max_avg
tuple f()
, можно просто написать return {foo_instance, bar_ instance, baz_instance};
внутри этой функции, чтобы создать такой кортеж. Если вам трудно понять использованные нами алгоритмы STL, то, вероятно, следует обратиться к главе 5, где мы уже рассмотрели их подробнее.Остальной код настолько сложен, что мы посвятим конкретным вспомогательным функциям отдельные подразделы.
operator<< для кортежей
До работы с operator<<
print_args
. Из-за своей природы он принимает произвольное количество аргументов разных типов до тех пор, пока первым из них является экземпляр типа ostream
:template
void print_args(ostream &os, const T &v, const Ts &. vs)
{
os << v;
(void)initializer_list
}