[БЕЗ_ЗВУКА] В данной лекции мы рассмотрим, как можно улучшить наш код. Мы уберем дублирование в операторах вывода вектора и map в поток. Дублирование выражено в том, что мы везде делаем одинаковые итерации. И, более того, у нас везде закралась одинаковая ошибка. Мы везде в операторах вывода добавляем лишний пробел. Это будет видно, если мы, например, его заменим на запятую. Попробуем запустить наш код. Видим, что в конце появилась лишняя запятая. И это выглядит не очень красиво. А также мы сделаем наш вывод более читаемым. Вокруг вектора будем рисовать квадратные скобки, вокруг map — фигурные. И пары будем выводить в круглых скобочках. Что ж, приступим. Значит, как можно убрать дублирование кода в операторах вывода вектора и map? Нужно создать универсальную функцию, шаблонную, которая на вход будет принимать некую коллекцию, по которой можно итерироваться с помощью цикла range-based for. И на вход этой функции будем передавать некий разделитель, через который надо вывести элементы нашей коллекции. Единственное, что мы требуем от входной коллекции, это следующие два условия: по ней можно итерироваться с помощью цикла range-based for, и ее элементы можно выводить в поток. Приступим. Пусть наш шаблонный параметр — тип будет называться collection. Из функции мы возвращаем строку. Первым аргументом передаем коллекцию. Вторым — разделитель. Заводим строковый поток. Объявляем флажок, который будет говорить нам, первые мы элементы выводим или нет. Далее в цикле range-based for мы итерируемся по нашей коллекции. Далее, если мы выводим не первый элемент, то в наш поток мы кладем разделитель. После этого, совершенно точно мы уже не будем выводить первый элемент, поэтому кладем флажок false. Приравниваем флажок first значению false. И кладем в наш строковый поток элемент коллекции, и после этого возвращаем строку, получившуюся строчку. Давайте применим данную функцию внутри оператора, шаблонного оператора вывода в поток вектора. Как он будет выглядеть после этого? Значит, в поток out мы будем выводить результат функции Join, которая на вход принимает вектор и разделитель. Пусть это точно так же будет запятая. Так как операторы вывода в поток возвращают ссылку на поток, в который они выводят, мы сразу же в этой строчке можем написать return. И это вообще будет функция-однострочник. Соберем наш код. Запустим его. И видим, что действительно, в первой строке, там, где мы выводим вектор (давайте я опущусь до функции main, вот у нас идет вывод вектора), в этой строке у нас пропала в конце запятая. Значит, теперь мы смело можем убрать дублирование в оператор и вывода в поток для map. [БЕЗ_ЗВУКА] Более того, давайте сразу сделаем аргумент, обозначим аргумент другой буквой. Соберем наш код. Видим, что он собрался без ошибок. Запустим его. Видим, что map теперь тоже выводится без запятой в конце. Осталось сделать вывод чуть более читабельным. Добавим скобочки. [БЕЗ_ЗВУКА] [БЕЗ_ЗВУКА] А вокруг пары добавим круглые скобки. Соберем наш код. Запустим его. И, кстати, вывод пары может быть написан тоже в одну строчку. Бинго. Мы видим, что теперь просто по выводу в консоль мы понимаем, что первой строкой мы вывели вектор, который состоит просто из элементов 1.4, 2 и 3. А второй строкой мы вывели уже словарь, который состоит из элементов: 1, 2.5 и так далее. Давайте проверим, на всякий случай, что наши операторы вывода работают и для более сложных конструкций типов, например, пусть у нас будет вектор векторов. Вот так вот. Значит, объявим первый вектор из элементов 1, 2, второй вектор из элементов 3, 4. Соберем наш код. Запустим его. Видим, что действительно все сработало, так, как мы ожидаем. Значит, еще раз пробежимся по коду, который мы написали. Здесь мы объявили вектор и пытаемся вывести его в поток. Далее, компилятор ищет функцию, которая наиболее подходит под вывод вектора в поток. Она находит оператор вывода для словаря, для вектора и для пары. Лучше всех из них подходит оператор вывода для вектора. После этого мы выводим в поток скобочку и далее результат функции Join. Функция Join у нас шаблонная. Как она определена? На вход она принимает некую коллекцию, которая должна выполнять два требования. По ней можно итерироваться с помощью цикла range-based for. И ее элементы должно быть можно выводить в поток. То есть вот именно в этой строке мы выводим ее элементы в поток. Для них обязана быть доступной эта функция. После этого мы с помощью этой шаблонной функции итерируемся по нашей коллекции, выводим ее в поток и возвращаем склеенную строчку через разделитель. Заметьте, как сильно преобразился наш код. Вместо дублирования одних и тех же циклов в разных операторах вывода мы сделали одну универсальную функцию, и все наши операторы вывода сейчас превратились в функцию-однострочник с минимальным дублированием кода.