- Фантастика и фэнтези
- Ироническое фэнтези
- Стимпанк
- Детективная фантастика
- Киберпанк
- Попаданцы
- LitRPG
- Космоопера
- Технофэнтези
- Городская фантастика
- Русское фэнтези
- Юмористическая фантастика
- Космическая фантастика
- Боевое фэнтези
- Эпическая фантастика
- Зарубежная фантастика
- Книги магов
- Мистика
- Разная фантастика
- Разное фэнтези
- Любовное фэнтези
- Романтическая фантастика
- Городское фентези
- Историческая фантастика
- Историческое фэнтези
- Социально-философская фантастика
- Сказочная фантастика
- Иностранное фэнтези
- Романтическое фэнтези
- Ироническая фантастика
- Ужасы и Мистика
- Постапокалипсис
- Героическая фантастика
- Фэнтези
- Научная Фантастика
- Социально-психологическая
- Альтернативная история
- Боевая фантастика
- Разная литература
- Пословицы, поговорки
- Шахматы
- Визуальные искусства
- Фанфик
- Авто и ПДД
- Военное
- Отраслевые издания
- Гиды, путеводители
- Зарубежная образовательная литература
- Военная история
- Цитаты из афоризмов
- Современная литература
- Великолепные истории
- Начинающие авторы
- Современная зарубежная литература
- Боевые искусства
- Изобразительное искусство, фотография
- Кино
- Литература 19 века
- Недвижимость
- Музыка, музыканты
- Готические новеллы
- Истории из жизни
- Культура и искусство
- Спецслужбы
- Зарубежная прикладная литература
- Музыка, танцы
- Подростковая литература
- Прочее
- Военная техника, оружие
- Газеты и журналы
- Периодические издания
- Домоводство, Дом и семья
- Любовные романы
- Экономическая литература
- Научные и научно-популярные книги
- О животных
- Биохимия
- Культурология
- Юриспруденция
- Политика
- Психотерапия
- Языкознание
- Научпоп
- Медицина
- Психология, личное
- Радиотехника
- Филология
- Педагогика
- Образовательная литература
- Деловая литература
- Физика
- Науки: разное
- Химия
- Воспитание детей, педагогика
- Детская психология
- Зарубежная публицистика
- Биология
- Архитектура
- Зарубежная психология
- Науки о космосе
- Социология
- Математика
- География
- Беременность, ожидание детей
- Литературоведение
- Транспорт, военная техника
- Обществознание
- Зоология
- География
- Альтернативная медицина
- Иностранные языки
- Ветеринария
- Рефераты
- Астрология
- Биофизика
- Экология
- История Европы
- Учебники
- Шпаргалки
- Государство и право
- Ботаника
- Религиоведение
- История
- Техническая литература
- Прочая научная литература
- Психология
- Детективы и Триллеры
- Справочная литература
- Проза
- Новелла
- Юмор
- Проза
- Историческая проза
- Русская современная проза
- Советская классическая проза
- Повести
- Очерки
- Эссе
- Рассказы
- Зарубежная современная проза
- Сентиментальная проза
- Зарубежная классика
- Афоризмы
- Эпистолярная проза
- Феерия
- Семейный роман/Семейная сага
- Разное
- Антисоветская литература
- Магический реализм
- Русская классическая проза
- Современная проза
- О войне
- Контркультура
- Классическая проза
- Поэзия, Драматургия
- Детская литература
- Детская фантастика
- Детские остросюжетные
- Детские стихи
- Детские приключения
- Внеклассное чтение
- Учебная литература
- Зарубежные детские книги
- Бизнес
- Загадки
- Книги для подростков
- Школьные учебники
- Детский фольклор
- Книги для дошкольников
- Детские детективы
- Детская познавательная и развивающая литература
- Буквари
- Прочая детская литература
- Сказка
- Детская проза
- Детская образовательная литература
- Юмор
- Документальные книги
- Бизнес
- Внешнеэкономическая деятельность
- Тайм-менеджмент
- Кадровый менеджмент
- О бизнесе популярно
- Управление, подбор персонала
- Бизнес
- Менеджмент и кадры
- Продажи
- Экономика
- Ценные бумаги и инвестиции
- Малый бизнес
- Делопроизводство, офис
- Корпоративная культура, бизнес
- Банковское дело
- Финансы
- Зарубежная деловая литература
- Ораторское искусство / риторика
- Личные финансы
- Интернет-бизнес
- Поиск работы
- Государственное и муниципальное управление
- Бухучет и аудит
- Работа с клиентами
- Менеджмент
- Краткое содержание
- Личная эффективность
- Переговоры
- Приключения
- Старинная литература
- Религия и духовность
- Компьютеры и Интернет
- Блог
Читаем без скачивания C++17 STL Стандартная библиотека шаблонов - Яцек Галовиц
Шрифт:
Интервал:
Закладка:
Начиная с С++11 создавать подобные замыкания стало проще:
#include <iostream>
int main() {
auto greet_john_doe ([] {
std::cout << "Hello, John Doen";
});
greet_john_doe();
}
На этом все. Целая структура name_greeter заменяется небольшой конструкцией [] { /* сделать что-то */ }, которая на первый взгляд выглядит странно, но уже в следующем разделе мы рассмотрим все возможные случаи ее применения.
Лямбда-выражения помогают поддерживать код обобщенным и чистым. Они могут применяться как параметры для обобщенных алгоритмов, чтобы уточнить их при обработке конкретных типов, определенных пользователем. Они также могут служить для оборачивания рабочих пакетов и данных, чтобы их можно было запускать в потоках или просто сохранять работу и откладывать само выполнение пакетов. После появления С++11 было создано множество библиотек, работающих с лямбда-выражениями, поскольку они стали естественной частью языка С++. Еще одним вариантом использования лямбда-выражений является метапрограммирование, поскольку они могут быть оценены во время выполнения программы. Однако мы не будем рассматривать этот вопрос, так как он не относится к теме данной книги.
В текущей главе мы в значительной мере будем опираться на отдельные шаблоны функционального программирования, которые могут показаться странными для новичков и даже опытных программистов, еще не работавших с такими шаблонами. Если в последующих примерах вы увидите лямбда-выражения, возвращающие лямбда-выражения, которые опять-таки возвращают лямбда-выражения, то, пожалуйста, не теряйтесь. Мы несколько выходим за рамки привычного стиля программирования, чтобы подготовиться к работе с современным языком С++, в котором шаблоны функционального программирования встречаются все чаще и чаще. Если код какого-то примера выглядит слишком сложным, то уделите время тому, чтобы подробнее разобрать его. Как только вы с этим разберетесь, сложные лямбда-выражения в реальных проектах больше не будут вас смущать.
Динамическое определение функций с помощью лямбда-выражений
Применяя лямбда-выражения, можно инкапсулировать код, чтобы вызвать его позже или даже в другом месте, поскольку его разрешено копировать. Кроме того, можно инкапсулировать код несколько раз с несколько различающимися параметрами, при этом не нужно будет реализовывать новый класс функции для этой задачи.
Синтаксис лямбда-выражений выглядел новым в С++11, и к С++17 он несколько изменился. В этом разделе мы увидим, как сейчас выглядят лямбда-выражения и что они означают.
Как это делается
В этом примере мы напишем небольшую программу, в которой поработаем с лямбда-выражениями, чтобы понять основные принципы взаимодействия с ними.
1. Для работы с лямбда-выражениями не нужна поддержка библиотек, но мы будем выводить сообщения на консоль и использовать строки, поэтому понадобятся соответствующие заголовочные файлы:
#include <iostream>
#include <string>
2. В данном примере все действие происходит в функции main. Мы определим два объекта функций, которые не принимают параметры, и вернем целочисленные константы со значениями 1 и 2. Обратите внимание: выражение return окружено фигурными скобками {}, как это делается в обычных функциях, а круглые скобки (), указывающие на функцию без параметров, являются необязательными, мы не указываем их во втором лямбда-выражении. Но квадратные скобки [] должны присутствовать:
int main()
{
auto just_one ( [](){ return 1; } );
auto just_two ( [] { return 2; } );
3. Теперь можно вызвать оба объекта функций, просто написав имя переменных, которые в них сохранены, и добавив скобки. В этой строке их не отличить от обычных функций:
std::cout << just_one() << ", " << just_two() << 'n';
4. Забудем о них и определим еще один объект функции, который называется plus, — он принимает два параметра и возвращает их сумму:
auto plus ( [](auto l, auto r) { return l + r; } );
5. Использовать такой объект довольно просто, в этом плане он похож на любую другую бинарную функцию. Мы указали, что его параметры имеют тип auto, вследствие чего объект будет работать со всеми типами данных, для которых определен оператор +, например со строками.
std::cout << plus(1, 2) << 'n';
std::cout << plus(std::string{"a"}, "b") << 'n';
6. Не нужно сохранять лямбда-выражение в переменной, чтобы использовать его. Мы также можем определить его в том месте, где это необходимо, а затем разместить параметры для данного выражения в круглых скобках сразу после него (1, 2):
std::cout
<< [](auto l, auto r){ return l + r; }(1, 2)
<< 'n';
7. Далее определим замыкание, которое содержит целочисленный счетчик. При каждом вызове значение этого счетчика будет увеличиваться на 1 и возвращать новое значение. Для указания на то, что замыкание содержит внутренний счетчик, разместим в скобках выражение count = 0 — оно указывает, что переменная count инициализирована целочисленным значением 0. Чтобы позволить ему изменять собственные переменные, мы используем ключевое слово mutable, поскольку в противном случае компилятор не разрешит это сделать:
auto counter (
[count = 0] () mutable { return ++count; }
);
8. Теперь вызовем объект функции пять раз и выведем возвращаемые им значения с целью увидеть, что значение счетчика увеличивается:
for (size_t i {0}; i < 5; ++i) {
std::cout << counter() << ", ";
}
std::cout << 'n';
9. Мы также можем взять существующие переменные и захватить их по ссылке вместо того, чтобы создавать копию значения для замыкания. Таким образом, значение переменной станет увеличиваться в замыкании и при этом будет доступно за его пределами. Для этого мы поместим в скобках конструкцию &a, где символ & означает, что мы сохраняем ссылку на переменную, но не копию:
int a {0};
auto incrementer ( [&a] { ++a; } );
10. Если это работает, то можно вызвать данный объект функции несколько раз, а затем пронаблюдать, действительно ли меняется значение переменной a:
incrementer();
incrementer();
incrementer();
std::cout
<< "Value of 'a' after 3 incrementer() calls: "
<< a << 'n';
11. Последний пример демонстрирует каррирование.