Читать книги » Книги » Компьютеры и Интернет » Программирование » C++17 STL Стандартная библиотека шаблонов - Яцек Галовиц

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

Читать книгу C++17 STL Стандартная библиотека шаблонов - Яцек Галовиц, Яцек Галовиц . Жанр: Программирование.
C++17 STL Стандартная библиотека шаблонов - Яцек Галовиц
Название: C++17 STL Стандартная библиотека шаблонов
Дата добавления: 15 июль 2023
Количество просмотров: 1 473
(18+) Внимание! Книга может содержать контент только для совершеннолетних. Для несовершеннолетних просмотр данного контента СТРОГО ЗАПРЕЩЕН! Если в книге присутствует наличие пропаганды ЛГБТ и другого, запрещенного контента - просьба написать на почту для удаления материала.
Читать онлайн

C++17 STL Стандартная библиотека шаблонов читать книгу онлайн

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

С++ — объектно-ориентированный язык программирования, без которого сегодня немыслима промышленная разработка ПО. В этой замечательной книге описана работа с контейнерами, алгоритмами, вспомогательными классами, лямбда-выражениями и другими интересными инструментами, которыми богат современный С++. Освоив материал, вы сможете коренным образом пересмотреть привычный подход к программированию.
Преимущество издания — в подробном описании стандартной библиотеки шаблонов С++, STL. Ее свежая версия была выпущена в 2017 году. В книге вы найдете более 90 максимально реалистичных примеров, которые демонстрируют всю мощь STL. Многие из них станут базовыми кирпичиками для решения более универсальных задач.
Вооружившись этой книгой, вы сможете эффективно использовать С++17 для создания высококачественного и высокопроизводительного ПО, применимого в различных отраслях.

1 ... 36 37 38 39 40 ... 121 ВПЕРЕД
Перейти на страницу:
0;

}

static bool ends_with_b (const std::string &s)

{

  return s.rfind("b") == s.length() - 1;

}

3. Теперь реализуем вспомогательную функцию и назовем ее combine. Она принимает бинарную функцию в качестве первого параметра — это может быть, например, логическое И либо логическое ИЛИ. Затем она принимает два других параметра, представляющих собой две функции-предиката, которые нужно объединить:

template <typename A, typename B, typename F>

auto combine(F binary_func, A a, B b)

{

4. Просто возвращаем лямбда-выражение, которое захватывает новую комбинацию предикатов. Оно направляет параметр обоим предикатам, а затем помещает результаты работы их обоих в бинарную функцию и возвращает ее результат:

  return [=](auto param) {

    return binary_func(a(param), b(param));

  };

}

5. Укажем, что будем использовать пространство имен std с целью сэкономить немного времени при написании функции main:

using namespace std;

6. Теперь объединим две функции-предиката в другую функцию-предикат, говорящую, начинается ли заданная строка с символа a и заканчивается ли символом b, как, например, строки "ab" или "axxxb". На роль бинарной функции выбираем std::logical_and. Это шаблонный класс, экземпляр которого нужно создавать, вследствие чего будем использовать его вместе с фигурными скобками. Обратите внимание: мы не предоставляем дополнительный параметр шаблона, поскольку для данного класса он по умолчанию будет равен void. Эта специализация класса самостоятельно выводит все типы параметров:

int main()

{

  auto a_xxx_b (combine(

    logical_and<>{},

    begins_with_a, ends_with_b));

7. Итерируем по стандартному потоку ввода и выводим на экран все слова, которые удовлетворяют условиям предиката:

  copy_if(istream_iterator<string>{cin}, {},

    ostream_iterator<string>{cout, ", "},

    a_xxx_b);

  cout << 'n';

}

8. Компиляция и запуск программы дадут следующий результат. Мы передаем программе четыре слова, но только два из них удовлетворяют условиям предиката:

$ echo "ac cb ab axxxb" | ./combine

ab, axxxb,

Дополнительная информация

Библиотека STL уже предоставляет несколько функциональных объектов наподобие std::logical_and, std::logical_or, а также множество других, поэтому не нужно реализовывать их в каждом проекте. Ознакомиться со справочным материалом по С++ и исследовать доступные варианты можно на http://en.cppreference.com/w/cpp/utility/functional.

Вызываем несколько функций с одинаковыми входными данными

 Существует множество задач, чьи решения требуют написания повторяющегося кода. Большую его часть можно легко заменить лямбда-выражениями, и очень просто создать вспомогательную функцию, которая будет оборачивать подобные повторяющиеся задачи.

В данном разделе мы поработаем с лямбда-выражениями, чтобы направить один вызов функции со всеми его параметрами нескольким получателям. Мы сделаем это, не задействовав никаких дополнительных структур данных, так что перед компилятором будет стоять простая задача: сгенерировать бинарный файл без лишних затрат.

Как это делается

В этом примере мы напишем вспомогательную функцию для работы с лямбда-выражениями, которая направляет один вызов нескольким объектам, и еще одну такую функцию, направляющую один вызов нескольким функциям. Эту комбинацию мы используем в нашем примере, чтобы вывести на экран одно сообщение с помощью разных функций-принтеров.

1. Включим заголовочный файл, необходимый для вывода данных на экран:

#include <iostream>

2. Сначала реализуем функцию multicall, которая является основной для этого примера. Она принимает произвольное количество функций в качестве параметров и возвращает лямбда-выражение, принимающее один параметр. Она перенаправляет данный параметр всем функциям, предоставленным ранее. Таким образом, можно определить функцию auto call_all(multicall(f,g,h)), а затем вызов call_all(123) приведет к серии вызовов f(123); g(123); h(123);. Эта функция уже выглядит сложной, поскольку требуется распаковать набор параметров, в котором находятся функции, в набор вызовов с помощью конструктора std::initializer_list.

static auto multicall (auto ...functions)

{

  return [=](auto x) {

    (void)std::initializer_list<int>{

      ((void)functions(x), 0)...

    };

  };

}

3. Следующая вспомогательная функция принимает функцию f и набор параметров xs. После этого она вызывает функцию f для каждого из параметров. Таким образом, вызов for_each(f,1,2,3) приводит к серии вызовов: f(1); f(2); f(3);. Функция, по сути, использует такой же синтаксический прием для распаковки набора параметров xs в набор вызовов функций, как и функция, показанная ранее.

static auto for_each (auto f, auto ...xs) {

  (void)std::initializer_list<int>{

    ((void)f(xs), 0)...

  };

}

4. Функция brace_print принимает два символа и возвращает новый объект функции, принимающий один параметр x. Она выводит его на экран, окружив двумя символами, которые мы только что захватили.

static auto brace_print (char a, char b) {

  return [=] (auto x) {

    std::cout << a << x << b << ", ";

  };

}

5. Теперь наконец можно использовать все эти функции в функции main. Сначала определим функции f, g и h. Они представляют функции print, которые принимают значения и выводят их на экран, окружив разными скобками. Функция nl принимает любой параметр и просто выводит на экран символ переноса строки.

int main()

{

  auto f (brace_print('(', ')'));

  auto g (brace_print('[', ']'));

  auto h (brace_print('{', '}'));

  auto nl ([](auto) { std::cout << 'n'; });

6. Объединим все эти функции с помощью вспомогательной функции multicall:

  auto call_fgh (multicall(f, g, h, nl));

7. Мы хотим, чтобы каждое предоставленное нами число было выведено на экран трижды в разных скобках. Таким образом, нужно выполнить один вызов функции, который приведет к пяти вызовам нашей мультифункции, а та, в свою очередь, выполнит четыре вызова для функций f, g, h и nl:

  for_each(call_fgh, 1, 2, 3, 4, 5);

}

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

$ ./multicaller

(1), [1], {1},

(2), [2], {2},

(3), [3], {3},

(4), [4], {4},

(5), [5], {5},

Как это работает 

Вспомогательные функции, которые мы только что реализовали, выглядят очень сложными. Так произошло из-за распаковки набора параметров с помощью std::initializer_list. Почему мы вообще использовали эту структуру данных? Еще раз взглянем на for_each:

auto for_each ([](auto f, auto

1 ... 36 37 38 39 40 ... 121 ВПЕРЕД
Перейти на страницу:
Комментарии (0)