[](int i){std::cout << i << "\n";});
С возвращаемыми значениями всё почти так же просто. Если тело лямбда-функции состоит из единственного предложения return
, то тип возвращаемого ей значения совпадает с типом возвращаемого выражения. Например, такую простую лямбда-функцию можно было бы использовать для проверки флага, ожидаемого условной переменной std::condition_variable
(см. раздел 4.1.1).
Листинг А.4. Простая лямбда-функция с выводимым типом возвращаемого значения
std::condition_variable cond;
bool data_ready;
std::mutex m;
void wait_for_data() {
std::unique_lock
cond.wait(lk, []{return data_ready;}); ←
(1)
}
Тип значения, возвращаемого лямбда-функцией, которая передана cond.wait()
(1), выводится из типа переменной data_ready
, то есть совпадает с bool
. Когда условная переменная получает сигнал, она вызывает эту лямбда-функцию, захватив предварительно мьютекс, и wait()
возвращает управление, только если data_ready
равно true
.
Но что если невозможно написать тело лямбда-функции, так чтобы оно содержало единственное предложение return
? В таком случае тип возвращаемого значения следует задать явно. Это return
, но ->
), а за ней указать тип. Если лямбда-функция не имеет параметров, то список параметров (пустой) все равно необходим, иначе задать тип возвращаемого значения невозможно. Таким образом, предикат, проверяемый условной переменной, можно записать так:
cond.wait(lk, []()->bool{ return data_ready; });
Лямбда-функции с явно заданным типом возвращаемого значения можно использовать, например, для записи сообщений в журнал или для более сложной обработки:
cond.wait(lk, []()->bool {
if (data_ready) {
std::cout << "Данные готовы" << std::endl;
return true;
} else {
std::cout <<
"Данные не готовы, продолжаю ждать" << std::endl;
return false;
}
});
Даже такие простые лямбда-функции весьма полезны и существенно упрощают код, но их истинная мощь проявляется, когда требуется запомнить локальные переменные.
A.5.1. Лямбда-функции, ссылающиеся на локальные переменные
Лямбда-функции с []
не могут ссылаться на локальные переменные из объемлющей области видимости; им разрешено использовать только глобальные переменные и то, что передано в параметрах. Чтобы получить доступ к локальной переменной, ее нужно [=]
. Теперь лямбда-функция может получить доступ к
Рассмотрим этот механизм на примере следующей простой функции:
std::function
return [=](int j){return offset+j;};
}
При каждом вызове make_offseter
с помощью обертки std::function<>
создается новый содержащий лямбда-функцию объект. Возвращенная функция добавляет указанное смещение к любому переданному ей параметру. Например, следующая программа
int main() {
std::function
std::function
std::cout <<
offset_42(12) << "," << offset_123(12) << std::endl;
std::cout <<
offset_42(12) << "," << offset_123(12) << std::endl;
}