Эта функция выводит на экран первый элемент v
vs
. Мы выводим на экран первый элемент отдельно, поскольку хотим, чтобы все элементы были разделены запятыми, но не хотим, чтобы строка начиналась или заканчивалась запятой (например, "1,2,3, "
или ",1,2,3"
). Мы узнали о приеме с разворачиванием initializer_list
из примера «Вызов нескольких функций с одними и теми же входными данными» главы 4. Подготовив эту функцию, мы получили все необходимое для вывода кортежей на экран. Наша реализация оператора <<
выглядит следующим образом:template
ostream& operator<<(ostream &os, const tuple
{
auto capt_tup ([&os](const auto &...xs) {
print_args(os, xs...);
});
os << "(";
apply(capt_tup, t);
return os << ")";
}
Первое, что мы делаем, — это определяем объект функции capt_tup
capt_tup(foo, bar, whatever)
приводит к вызову print_args(os, foo, bar, whatever)
. Данный объект функции делает только одно: добавляет к списку аргументов объект потока вывода os
.После этого мы воспользуемся методом std::apply
t
. Если данный шаг выглядит слишком сложным, обратитесь к предыдущему примеру — он демонстрирует работу метода std::apply
.Функция zip для кортежей
Функция zip
template
auto zip(const T1 &a, const T2 &b)
{
auto z ([](auto ...xs) {
return [xs...](auto ...ys) {
return tuple_cat(make_tuple(xs, ys) ...);
};
});
return apply(apply(z, a), b);
}
Для лучшего понимания этого кода представьте, что кортеж a
1
, 2
, 3
, а кортеж b
— значения 'a'
, 'b'
, 'c'
.В данном случае вызов apply(z, a)
z(1, 2, 3)
. Он вернет объект функции, который захватит значения 1
, 2
, 3
в набор параметров xs
. В момент вызова с помощью apply(z(1,2,3),b)
этот объект получит значения 'a'
, 'b'
, 'c'
, помещенные в набор параметров ys
. По сути, действие аналогично прямому вызову z(1,2,3)('a', 'b', 'c')
.О’кей, что произойдет теперь, когда у нас есть значения xs = (1, 2, 3)
ys = ('a', 'b', 'c')
? Выражение tuple_cat(make_tuple(xs, ys) ...)
сделает следующее (рис. 8.1).Сначала элементы из наборов xs
ys
будут сгруппированы попарно. Это «попарное чередование» выполняется в вызове make_tuple(xs,ys)
. Сначала мы получим список кортежей переменной длины по два элемента в каждом. Чтобы получить tuple_cat
— в результате получаем большой сконкатенированный кортеж, содержащий все члены исходных кортежей, которые чередуются. Замена void* с использованием std::any для повышения безопасности типов
Может случиться так: нам понадобится сохранить элементы
В прошлом мы имели возможность хранить указатели на различные объекты в указателе типа void*
Еще одним дополнением к STL в C++17 является тип std::any
В текущем разделе мы поработаем с этим вспомогательным типом для того, чтобы несколько лучше его понять.
Как это делается
В этом примере мы реализуем функцию, которая пробует вывести на экран какие-либо данные. В качестве ее типа аргумента служит тип std::any
1. Сначала включим необходимые заголовочные файлы и объявим об использовании пространства имен std
#include
#include
#include
#include
#include
using namespace std;
2. Чтобы сократить объем использования угловых скобок в следующей программе, определим псевдоним для типа list
using int_list = list