TGViewer
this->notes. this->notes. @thisnotes · 4.52K subscribers
Post #191 1.49K
#cpp

Лямбды 1/2.

1. Все мы помним, что список захвата работает только для локальных перенных. В то время как статические и глобальные переменные захватываются, грубо говоря, автоматически. Такое верно и для constexpr переменных, потому что в итоге у вас в коде будет подставлено конкретное значение. Логично и просто.
И тут стоит помнить, что константные интегральные типы неявно являются constexpr:

const int i = 1; // implicitly constexpr
const std::size_t j = 1ull; // implicitly constexpr
const float f = 1.f; // not implicitly constexpr


Т.е. первые две переменные мы можем не захватывать при использовании в лямбде, тогда как третью необходимо.

2. Immediately Invoked Function Expressions (IIFE).
Это довольно полезный подход использования лямбд, когда они вызываются сразу же:

[]{ std::cout << “ASD”; }();

Конечно в таком виде такое не используется. Гораздо более полезным такое будет, когда хочется инициализировать объект каким-то нетривиальным способом:

A a;
if (condition) {
a = firstWay();
} else {
a = secondWay();
}


Мы разделили инициализацию объекта на две части. Между ними он может быть невалидным, и использование до ифа может привести к уб. Как-то небезопасно и не оч поддерживаемо.
А ещё класс может не иметь конструктора по умолчанию, что в целом делает подход выше невозможным.
А ещё инициализируемая переменная может быть помечена const, что так же не даёт инициализировать её в ифе (в отличие от const в C++, в Java ключевое слово final, которое говорит, что переменной можно присвоить что-то только единожды -> код выше в случае final переменной заработает).

Если код достаточно простой, можно заюзать тернарный оператор:

const A a = condition ? firstWay() : secondWay();

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

const A a = [condition] {
if (condition) {
return firstWay();
} else {
return secondWay();
}
}();


Такой подход хорошо подходит для всех случаев, когда у вас действия происходят рядом с perfect forwarding:

std::vector<A> v;
v.emplace_back([condition] {
if (condition) {
return firstWay();
} else {
return secondWay();
}
}());


и другими функциями того же рода.

Есть поинт, что две скобки вызова лямбды в конце могут быть легко просмотрены (и можно подумать, что это просто лямбда, а не результат её выполнения), потому можно использовать std::invoke, но кмк тащить хедер ради такого не оч хорошо (только если он у вас уже был).

3. Вот тут (пункт 3) писал про приведение лямбд с пустым списком захвата к указателю на функцию.
Интересно, что такой хак работает не всегда:

auto* fptr = +[](auto i) {
return i * i;
};


Что в целом понятно и ожидаемо.

4. Вот тут таска (и чуть ниже ответ) про то, как сообразить call_once и call_n с помощью лямбд.
Кстати прикольно, что на нескольких различных докладах на CppCon чуваки говорили, что на ручных бенчмарках лямбда, инициализирующая статический объект, — более эффективна как реализация std::call_once чем собственно реализации в версиях стандартной библиотеки.

5. С появлением generic лямбд с C++14 вы можете писать примерно все обычные для шаблонов штуки вроде auto&& для универсальных ссылок или даже auto… для variadic templates. Ну и лямбды друг в друга можно передавать. Удобно.

6. Variable template lambda.
С C++14 можно создавать шаблонные переменные. И, что интересно, если вы используете лямбду для инициализации такой переменной, вы имеете доступ к шаблонному аргументу переменной:

template <typename T>
constexpr auto c_cast = [](auto x) {
return (T)x;
};


Тут, грубо говоря, вы получаете не просто шаблонный operator() в вашей лямбде, но и сам класс лямбды становится шаблонным.
  • 👍 10
  • 🔥 3
  • ❤ 1
More from @thisnotes
  1. Sep 17, 2026#common Сидите вы себе спокойно, разрабатываете поиск каких-нибудь объектов. Может это тов…
  2. Sep 9, 2026#cpp #books Да, книга 2001ого года. Мы ровесники. И да, в ней в основном обсуждаются какие…
  3. Sep 2, 2026#perf Попробовал собрать в кучку (кажется, немного сумбурно всё же) мысли по двум моментам…
  4. Aug 31, 2026Давайте новый тег заведём: #perf Во-первых, надо понять, что я вообще понимаю под перфом,…
  5. Aug 27, 2026#common Мы часто делаем системы, которые обладают какими-то ограничениями. Ограничения наш…
  6. Aug 24, 2026#list 0. [talk] Achieving Peak Performance for Matrix Multiplication in C++. Aliaksei Sala…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →