Неявный захват константы
#include <iostream>
void bar(int x) { std::cout << x << '\n'; }
void foo() {
const int x = 42;
[](){ bar(x); }();
}
int main() { foo(); }
Почему программа компилируется, если x -- константа, и не компилируется в противном случае?
error: 'x' is not captured
Ответы (1 шт):
Тут дело тонкое.
x - неявно constexpr, потому что она const, имеет целочисленный тип, и инициализируется константой времени компиляции. ([expr.const]/4 и выше)
Использование constexpr переменных в лямбде требует захвата только если вы используете адрес переменной (и переменная не глобальная и не статическая). Если вы используете только значение, а не адрес, в захвате нет необходимости. ([expr.prim.lambda.capture]/11)
Такое использование адреса constexpr переменной называется odr-использованием (odr-use) переменной (от слова one definition rule), и делает захват обязательным. Для не-constexpr переменной даже ее использование без взятия адреса считается odr-использованием, поэтому их захват обязателен в любом случае. (вроде бы [basic.def.odr]/4, но там на эльфийском, на cppreference понятнее)
Интересно, что если в лямбде указан захват по умолчанию - = или &, то даже не-odr-использование переменной в лямбде может вызвать ее захват, если компилятор это не соптимизирует, хотя в отсутствие = и & все работало бы без захвата. (пример в [expr.prim.lambda.capture]/7)