group-telegram.com/cxx95/48
Create:
Last Update:
Last Update:
#books
Обзор книги "C++ Lambda Story" 📚
(можно посмотреть тут - https://leanpub.com/cpplambda)
Как известно, язык C++ очень простой, всего лишь за 157 страниц можно понять, как работают лямбды в C++ ✨
Перед прочтением можно пересмотреть видеоприкол C++ Lambda Ace Attorney 😃
В книге есть исследование по всей сфере вопроса: как без лямбд обходились до C++11, и как возможности лямбд расширялись от стандарта к стандарту (C++14/17/20).
Изначальная идея лямбд простая - запись
auto lam = [](double param) { /* do something */ };...функционально должна работать примерно как
struct {...то есть быть более простой записью для функтора (объект класса с
void operator()(double param) const { /* do something */ }
} lam;
operator()
), которые широко использовались в C++98/03.Все дальнейшие изменения в дизайне лямбд связаны с общим развитием языка, чтобы приспособить к функтору новые фичи.
Книга дает представление, как лямбды выглядят "внутри", поэтому многие рассмотренные вопросы становятся самоочевидными:
🤔 почему capture нужно делать только для автоматических переменных;
🤔 как делать capture для
this
;🤔 серьезная разница между лямбдами которые ничего не capture-ят, и которые делают это; и многое другое...
Многое я уже знал заранее (даже лазил в части компилятора, который генерирует лямбды), поэтому мне было интересно, найдутся ли неизвестные мне интересные факты? Оказалось, что такое есть:
🚀 Начиная с C++20 можно создавать объект лямбды (раньше было нельзя)
auto foo = [](int a, int b) { return a + b; };это нужно для передачи типа лямбды, например как параметра в
decltype(foo) bar;
// ^ (до C++20) error: no matching constructor for initialization of 'decltype(foo)'
std::set
- пример на godbolt🚀 Начиная с C++17 можно использовать std::invoke для улучшения читабельности в немедленных вызовах лямбд:
auto v1 = [&]{ /* .../ }();пример на godbolt
auto v2 = std::invoke([&]{ /* .../ });
🚀 Если лямбда ничего не capture-ит, то она может быть сконвертирована в указатель на функцию.
Если написать
+
перед лямбдой, то мы получим указатель на функцию, а не объект лямбды (потому что +
можно применять на указатель, а на объект лямбды нельзя).Это самый простой способ без
static_cast
-ов. Тред на stackoverflow.🚀 От лямбды (точнее от ее класса) можно унаследоваться разными способами.
В таком случае получившийся класс будет представлять из себя класс с несколькими
operator()(...)
(с разными аргументами). Есть несколько паттернов, где это применимо, но выглядит это довольно жутко и редко где нужно.Например, есть такой паттерн из доки для std::visit:
std::visit(overloaded{Остальные "приколы" меня не очень удивили: лямбды в контейнере, особенности лямбд в многопоточке, capture объекта
[](A a) { std::cout << a.name << std::endl; },
[](B b) { std::cout << b.type << std::endl; },
[](C c) { std::cout << c.age << std::endl; }
}, something);
[*this]
, шаблонные лямбды... Они выглядели самоочевидными, но кому-то может быть интересным 🙂BY C++95
Warning: Undefined variable $i in /var/www/group-telegram/post.php on line 260
Share with your friend now:
group-telegram.com/cxx95/48