- Фантастика и фэнтези
- Ироническое фэнтези
- Стимпанк
- Детективная фантастика
- Киберпанк
- Попаданцы
- LitRPG
- Космоопера
- Технофэнтези
- Городская фантастика
- Русское фэнтези
- Юмористическая фантастика
- Космическая фантастика
- Боевое фэнтези
- Эпическая фантастика
- Зарубежная фантастика
- Книги магов
- Мистика
- Разная фантастика
- Разное фэнтези
- Любовное фэнтези
- Романтическая фантастика
- Городское фентези
- Историческая фантастика
- Историческое фэнтези
- Социально-философская фантастика
- Сказочная фантастика
- Иностранное фэнтези
- Романтическое фэнтези
- Ироническая фантастика
- Ужасы и Мистика
- Постапокалипсис
- Героическая фантастика
- Фэнтези
- Научная Фантастика
- Социально-психологическая
- Альтернативная история
- Боевая фантастика
- Разная литература
- Пословицы, поговорки
- Шахматы
- Визуальные искусства
- Фанфик
- Авто и ПДД
- Военное
- Отраслевые издания
- Гиды, путеводители
- Зарубежная образовательная литература
- Военная история
- Цитаты из афоризмов
- Современная литература
- Великолепные истории
- Начинающие авторы
- Современная зарубежная литература
- Боевые искусства
- Изобразительное искусство, фотография
- Кино
- Литература 19 века
- Недвижимость
- Музыка, музыканты
- Готические новеллы
- Истории из жизни
- Культура и искусство
- Спецслужбы
- Зарубежная прикладная литература
- Музыка, танцы
- Подростковая литература
- Прочее
- Военная техника, оружие
- Газеты и журналы
- Периодические издания
- Домоводство, Дом и семья
- Любовные романы
- Экономическая литература
- Научные и научно-популярные книги
- О животных
- Биохимия
- Культурология
- Юриспруденция
- Политика
- Психотерапия
- Языкознание
- Научпоп
- Медицина
- Психология, личное
- Радиотехника
- Филология
- Педагогика
- Образовательная литература
- Деловая литература
- Физика
- Науки: разное
- Химия
- Воспитание детей, педагогика
- Детская психология
- Зарубежная публицистика
- Биология
- Архитектура
- Зарубежная психология
- Науки о космосе
- Социология
- Математика
- География
- Беременность, ожидание детей
- Литературоведение
- Транспорт, военная техника
- Обществознание
- Зоология
- География
- Альтернативная медицина
- Иностранные языки
- Ветеринария
- Рефераты
- Астрология
- Биофизика
- Экология
- История Европы
- Учебники
- Шпаргалки
- Государство и право
- Ботаника
- Религиоведение
- История
- Техническая литература
- Прочая научная литература
- Психология
- Детективы и Триллеры
- Справочная литература
- Проза
- Новелла
- Юмор
- Проза
- Историческая проза
- Русская современная проза
- Советская классическая проза
- Повести
- Очерки
- Эссе
- Рассказы
- Зарубежная современная проза
- Сентиментальная проза
- Зарубежная классика
- Афоризмы
- Эпистолярная проза
- Феерия
- Семейный роман/Семейная сага
- Разное
- Антисоветская литература
- Магический реализм
- Русская классическая проза
- Современная проза
- О войне
- Контркультура
- Классическая проза
- Поэзия, Драматургия
- Детская литература
- Детская фантастика
- Детские остросюжетные
- Детские стихи
- Детские приключения
- Внеклассное чтение
- Учебная литература
- Зарубежные детские книги
- Бизнес
- Загадки
- Книги для подростков
- Школьные учебники
- Детский фольклор
- Книги для дошкольников
- Детские детективы
- Детская познавательная и развивающая литература
- Буквари
- Прочая детская литература
- Сказка
- Детская проза
- Детская образовательная литература
- Юмор
- Документальные книги
- Бизнес
- Внешнеэкономическая деятельность
- Тайм-менеджмент
- Кадровый менеджмент
- О бизнесе популярно
- Управление, подбор персонала
- Бизнес
- Менеджмент и кадры
- Продажи
- Экономика
- Ценные бумаги и инвестиции
- Малый бизнес
- Делопроизводство, офис
- Корпоративная культура, бизнес
- Банковское дело
- Финансы
- Зарубежная деловая литература
- Ораторское искусство / риторика
- Личные финансы
- Интернет-бизнес
- Поиск работы
- Государственное и муниципальное управление
- Бухучет и аудит
- Работа с клиентами
- Менеджмент
- Краткое содержание
- Личная эффективность
- Переговоры
- Приключения
- Старинная литература
- Религия и духовность
- Компьютеры и Интернет
- Блог
Читаем без скачивания C++17 STL Стандартная библиотека шаблонов - Яцек Галовиц
Шрифт:
Интервал:
Закладка:
При десериализации элементов типа meme из потока мы разрешили использовать пробелы в названиях и описаниях. Это легко реализовать, однако они не длиннее одной строки, поскольку мы поместили данные поля в кавычки. Взгляните на пример формата строк: "Name with spaces" "Description with spaces" 123.
При работе со строками, заключенными в кавычки как на входе, так и на выходе, поможет std::quoted. Если у нас есть строка s, то при выводе ее с помощью cout << quoted(s) она будет заключена в кавычки. В случае десериализации строки из потока, например используя cin >> quoted(s), мы считаем следующий символ кавычек, заполним строку символами, стоящими после него, и будем делать это до тех пор, пока не увидим следующий символ кавычек, независимо от количества встреченных пробелов.
Последний необычный момент заключается в том, как мы передали функцию max_func в наш вызов алгоритма accumulate:
auto max_func ([](size_t old_max, const auto &b) {
return max(old_max, b.first.length());
});
size_t width {accumulate(begin(m), end(m), 0u, max_func)};
Похоже, что функция max_func принимает аргумент типа size_t и еще один аргумент с автоматическим типом, который оказывается элементом типа pair, взятым из ассоциативного массива. На первый взгляд все выглядит очень странно, поскольку большинство бинарных функций сжатия принимают аргументы идентичных типов, а затем объединяют их с помощью некой операции, как, например, это делает std::plus. В нашем случае все выглядит по-другому, поскольку мы не объединяем сами пары. Мы только получаем длину каждой строки, представляющей собой ключ, для каждой пары, отбрасываем остальное, а затем сжимаем полученные значения типа size_t с помощью функции max.
В вызове accumulate первый вызов функции max_func получает значение 0u, изначально предоставленное нами в качестве левого аргумента, и ссылку на первый элемент типа pair с правой стороны. Это дает возвращаемое значение max(0u, string_length), которое станет левым аргументом для следующего вызова, где очередная пара будет представлять собой правый параметр, и т.д.
Выводим любые данные на экран с помощью итераторов std::ostream
Очень легко вывести что-то на экран с помощью потоков вывода, поскольку в STL есть много полезных перегруженных версий оператора << для большинства простых типов. Таким образом, структуры данных, содержащие элементы подобных типов, можно легко вывести на экран, задействовав класс std::ostream_iterator, что мы довольно часто делали.
В данном примере мы сконцентрируемся на том, как это сделать для пользовательского типа и что еще можно сделать для управления выводом на экран с помощью выбора типа шаблона без необходимости писать при этом много кода на вызывающей стороне.
Как это делается
В этом примере мы поработаем с итератором std::ostream_iterator, объединив его с новым пользовательским классом, и взглянем на его возможности неявного преобразования, что может помочь при выводе данных на экран.
1. Сначала указываем, какие заголовочные файлы включить, а затем объявляем об использовании пространства имен std:
#include <iostream>
#include <vector>
#include <iterator>
#include <unordered_map>
#include <algorithm>
using namespace std;
2. Реализуем функцию преобразования, которая соотносит числа и строки. Она будет возвращать строку "one" для значения 1, "two" для значения 2 и т.д.:
string word_num(int i) {
3. Мы заполним ассоциативный массив, основанный на хешах, этими парами, чтобы получить к ним доступ позже:
unordered_map<int, string> m {
{1, "one"}, {2, "two"}, {3, "three"},
{4, "four"}, {5, "five"}, //...
};
4. Теперь можно передать в функцию find ассоциативного массива, основанного на хеше, аргумент i и вернуть то значение, которое она найдет. Если функция ничего не найдет — например, для заданного числа нет перевода, — то вернем строку "unknown":
const auto match (m.find(i));
if (match == end(m)) { return "unknown"; }
return match->second;
};
5. Мы будем работать также со структурой bork. Она содержит только одно целое число и неявно создается на основе целого числа. Кроме того, она имеет функцию print, которая принимает ссылку на поток вывода и выводит строку "bork" столько раз, сколько указано в целочисленной переменной borks:
struct bork {
int borks;
bork(int i) : borks{i} {}
void print(ostream& os) const {
fill_n(ostream_iterator<string>{os, " "},
borks, "bork!"s);
}
};
6. Для использования функции bork::print перегрузим оператор << для объектов потока, чтобы они автоматически вызывали функцию bork::print, когда объекты типа bork попадают в поток вывода:
ostream& operator<<(ostream &os, const bork &b) {
b.print(os);
return os;
}
7. Теперь наконец можем начать реализовывать саму функцию main. Изначально просто создаем вектор, содержащий некоторые значения:
int main()
{
const vector<int> v {1, 2, 3, 4, 5};
8. Для объектов типа ostream_iterator нужен параметр шаблона, который указывает, переменные какого типа они могут выводить. Если мы напишем ostream_iterator<T>, то в дальнейшем для вывода данных на экран будет применяться конструкция ostream& operator(ostream&, const T&). Именно это свойство мы и реализовали до типа bork. На сей раз просто выводим целые числа, поэтому специализация выглядит как ostream_iterator<int>. Для вывода информации на экран мы будем использовать поток cout, так что предоставим его в качестве параметра конструктора. Пройдем по вектору в цикле и присвоим каждый элемент i разыменованному итератору вывода. Именно так потоковые итераторы используются в алгоритмах STL.
ostream_iterator<int> oit {cout};
for (int i : v) { *oit = i; }
cout << 'n';
9. Полученный от итератора результат нам подходит, но он выводит числа без каких-либо разделителей. Если мы хотим добавить пробелы-разделители между всеми выведенными элементами, то можем предоставить собственную строку с пробелами в качестве второго параметра конструктора итератора выводного потока. Данное действие позволит вывести строку "1, 2, 3, 4, 5, " вместо строки "12345". К сожалению, мы не