KnigkinDom.org» » »📕 C++17 STL Стандартная библиотека шаблонов - Яцек Галовиц

C++17 STL Стандартная библиотека шаблонов - Яцек Галовиц

Книгу C++17 STL Стандартная библиотека шаблонов - Яцек Галовиц читаем онлайн бесплатно полную версию! Чтобы начать читать не надо регистрации. Напомним, что читать онлайн вы можете не только на компьютере, но и на андроид (Android), iPhone и iPad. Приятного чтения!

1 ... 81 82 83 84 85 86 87 88 89 ... 121
Перейти на страницу:

Шрифт:

-
+

Интервал:

-
+

Закладка:

Сделать
('a','b','c'), то она вернет кортеж (1,'a',2,'b',3,'c').

template <typename T1, typename T2>

static auto zip(const T1 &a, const T2 &b)

{

10. Мы подобрались к самым сложным строкам данного примера. Создадим объект функции z, принимающий произвольное количество аргументов. Затем он возвращает другой объект функции, который захватывает все эти аргументы в набор параметров xs, а также принимает произвольное количество аргументов. Забудем об этом на минуту. С помощью упомянутого внутреннего объекта функции можно получить доступ к обоим спискам аргументов в виде наборов параметров xs и ys. А теперь взглянем, что именно происходит с этими наборами параметров. Вызов make_tuple(xs,ys). группирует наборы параметров поэлементно. Т.е. при наличии наборов xs = 1,2,3 и ys = 'a','b','c' он вернет новый набор параметров (1,'a'), (2,'b'), (3,'c'). Данный набор представляет собой разделенный запятыми список, состоящий из трех кортежей. Чтобы объединить их в один кортеж, используем функцию std::tuple_cat, которая принимает произвольное количество кортежей и упаковывает их в один. Таким образом получим кортеж (1,'a',2,'b',3,'c').

  auto z ([](auto ...xs) {

    return [xs...](auto ...ys) {

      return tuple_cat(make_tuple(xs, ys) );

    };

  });

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<Foo, Bar, Baz> f(), можно просто написать return {foo_instance, bar_ instance, baz_instance}; внутри этой функции, чтобы создать такой кортеж. Если вам трудно понять использованные нами алгоритмы STL, то, вероятно, следует обратиться к главе 5, где мы уже рассмотрели их подробнее.

Остальной код настолько сложен, что мы посвятим конкретным вспомогательным функциям отдельные подразделы.

operator<< для кортежей

До работы с operator<< для потоков вывода мы реализовали функцию print_args. Из-за своей природы он принимает произвольное количество аргументов разных типов до тех пор, пока первым из них является экземпляр типа ostream:

template <typename T, typename Ts>

void print_args(ostream &os, const T &v, const Ts &. vs)

{

  os << v;

  (void)initializer_list<int>{((os << ", " << vs), 0)...};

}

Эта функция выводит на экран первый элемент v, а затем все элементы из набора параметров vs. Мы выводим на экран первый элемент отдельно, поскольку хотим, чтобы все элементы были разделены запятыми, но не хотим, чтобы строка начиналась или заканчивалась запятой (например, "1,2,3, " или ",1,2,3"). Мы узнали о приеме с разворачиванием initializer_list из примера «Вызов нескольких функций с одними и теми же входными данными» главы 4. Подготовив эту функцию, мы получили все необходимое для вывода кортежей на экран. Наша реализация оператора << выглядит следующим образом:

template <typename ... Ts>

ostream& operator<<(ostream &os, const tuple<Ts...> &t)

{

  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.

После этого

1 ... 81 82 83 84 85 86 87 88 89 ... 121
Перейти на страницу:
Отзывы - 0

Прочитали книгу? Предлагаем вам поделится своим отзывом от прочитанного(прослушанного)! Ваш отзыв будет полезен читателям, которые еще только собираются познакомиться с произведением.


Уважаемые читатели, слушатели и просто посетители нашей библиотеки! Просим Вас придерживаться определенных правил при комментировании литературных произведений.

  • 1. Просьба отказаться от дискриминационных высказываний. Мы защищаем право наших читателей свободно выражать свою точку зрения. Вместе с тем мы не терпим агрессии. На сайте запрещено оставлять комментарий, который содержит унизительные высказывания или призывы к насилию по отношению к отдельным лицам или группам людей на основании их расы, этнического происхождения, вероисповедания, недееспособности, пола, возраста, статуса ветерана, касты или сексуальной ориентации.
  • 2. Просьба отказаться от оскорблений, угроз и запугиваний.
  • 3. Просьба отказаться от нецензурной лексики.
  • 4. Просьба вести себя максимально корректно как по отношению к авторам, так и по отношению к другим читателям и их комментариям.

Надеемся на Ваше понимание и благоразумие. С уважением, администратор knigkindom.ru.


Партнер

Новые отзывы

  1. Р.Д.У. Р.Д.У.22 август 02:17 ...мне тоже понравился этот русский вестерн. И озвучено неплохо. Советую.... Силантьев Вадим – Засада
  2. Гость Любовь Гость Любовь21 август 20:01 Прочитала залпом.... интересный сюжет, история захватывает, плакала вместе с героями. спасибо автору за интересное... Вернуть жену. Без права на прощение? - Ира Орлова
  3. Ма Ма21 август 02:06 Роман хороший, но очень топорный и поэтому скучноватый, все как будто поверхностно, акцент на работе героев - киллер и главбух, а... Гектор - Ольга Дашкова
Все комметарии
Новое в блоге