in t Divisor = 2 ; / / Исходное значение
auto iElement = fin d _ if ( begin of a range
, end of a range
, [D iv iso r ](in t d ivid en d ){return (dividend
%Divisor) == 0; } );
Список аргументов передается как
переменная состояния
(state variable) в квадратных
скобках ( [ . . . ] ) и называется также списком захвата (capture list) лямбда-выражения.
ПРИМЕЧАНИЕ
|
Такое лямбда-выражение - это однострочный эквивалент 16 строк кода в ли
|
стинге 21.3, определяющего структуру унарного предиката is M u ltip le o .
|
|
|
Таким образом, лямбды стремительно повышают эффективность программи
|
|
рования на С++11!
|
Листинг 22.3 демонстрирует применение унарного предиката с заданной переменной
|
состояния для поиска в коллекции числа, кратного предоставляемому пользователем де лителю.
ЛИСТИНГ 22.3. Использование лямбда-выражений, хранящих
состояние для проверки кратности одного числа другому_____________________________________
0:
|
#include
|
|
1:
|
#include
|
|
2:
|
#include
|
|
3:
|
using namespace std;
|
4:
|
|
|
5:
|
in t main
|
()
|
6 : {
vector vecln tegers;
8:
|
cout «
|
"The vector
|
contains
|
the follow ing sample values: ";
|
9:
|
|
|
|
|
|
|
|
|
10:
|
/ /
|
Вставить примеры значений
|
от
|
25
|
до
|
31
|
11:
|
for
|
(int
|
nCount = 25;
|
nCount
|
<
|
32;
|
++
|
nCount)
|
1 2 :
|
{
|
|
|
|
|
|
|
|
veclntegers.push _back (nCount);
cout « nCount « ’ ';
}
16: cout « endl « "Enter d iv iso r (> 0): ";
in t Divisor = 2;
cin >> Divisor;
19
20/ / Найти первый элемент, кратный делителю
Обобщенный синтаксис лямбда-выражений
|
505
|
vector ::iterator iElement;
iElement = find_if ( veclntegers.begin ()
, veclntegers.end ()
, [Divisor](int dividend){return (dividend % Divisor) == 0; } );
if(iElement != veclntegers.end ())
{
cout « "First element in vector divisible by " << Divisor;
cout << ": " « *iElement << endl;
}
31:
return 0;
}
Результат
The vector contains the following sample values: 25 26 27 28 29 30 31
Enter divisor (> 0): 4
First element in vector divisible by 4: 28
Анализ
Лямбда-вы раж ение, хранящ ее состояние и работаю щ ее как предикат, пред
ставлено в строке 24. П ерем енная состояния D i v i s o r аналогична перем енной
I s M u l t i p l e : : D iv is o r , которую вы видели в листинге 21.3. Следовательно, переменные состояния сродни членам класса объекта функции, который вы использовали до С++11. Таким образом, теперь вы можете передать состояние в лямбда-функцию и настроить ее применение на его основании.
ПРИМЕЧАНИЕ Листинг 22.3 использует лямбда-эквивалент объекта функции из листинга 21.4,
но без класса. Одно средство C++11 сэкономило 16 строк кода!
Обобщенный синтаксис лямбда-выражений
Лямбда-выражение всегда начинается с квадратных скобок и может быть настроено так, чтобы получать несколько переменных состояния, разделенных запятыми в списке захвата [...]:
[StateVarl, StateVar2](Туре& param) { // здесь код лямбды; }
Если эти переменные состояния должны изменяться в пределах лямбды, добавьте клю чевое слово m u ta b le :
[StateVarl, StateVar2](Туре& param) mutable { // здесь код лямбды; }
Обратите внимание, что здесь передаваемые в списке захвата [ ] переменные допу скают изменение значений в пределах лямбды, но вовне эти изменения не передаются.
506 ЗАНЯТИЕ 22. Лямбда-выражения языка С++11
Если необходимо, чтобы внесенные в пределах лямбды изменения переменных распро странялись также во вне, используйте ссылки:
[SS tateV arl, & S tateV ar2](Туре& param) { / / здесь код лямбды; }
Лямбда-выражения могут получать по нескольку входных параметров, отделяемых запятыми:
[S ta te V a rl, StateVar2](Typel& v a r l , Type2& var2) { / / здесь код лямбды; }
Если хотите указать тип возвращаемого значения и не создавать неоднозначности для компилятора, используйте оператор -> так:
[ S ta te l, { r e tu r n
S ta te 2 ](T y p e l v a r l , ( / / здесь значение
Type2 var2) -> или выражение);
ReturnType
}
наконец, составной оператор {} может содержать несколько операторов, разделен ных точкой с запятой (;), как показано ниже:
[ S ta te l, S ta te 2 ](T y p e l v a r l ,
Type2
var2) ->
ReturnType
{ Statem ent 1; Statem ent 2;
r e tu r n
( / / здесь
значение
или выражение);
}
ПРИМЕЧАНИЕ
В случае, если лямбда-выражение распространяется на несколько строк, тип возвращаемого значения следует указать явно.
листинге 22.5 показана лямбда-функция, определяющая тип возвращаемого значения и охватывающая несколько строк.
Таким образом, лямбда-функция — это компактная, полнофункциональная замена та кого объекта функции, как следующий:
tem platectypename
|
Typel,
|
typename
|
Туре2>
|
s t r u c t
|
IsNowTooLong
|
|
|
{
|
|
|
|
|
|
|
/ /
|
переменные
|
состояния
|
|
Typel
|
v a r l ;
|
|
|
|
|
Type2
|
var2;
|
|
|
|
|
/ /
|
Конструктор
|
|
|
|
IsNowTooLong(const Typel& i n i ,
|
Type2& i n 2 ) : v a r l ( i n l ) , var2 (in 2 ) {};
|
/ /
|
фактическая
|
цель
|
|
|
ReturnType
|
o p e r a t o r ()
|
|
|
{
|
Statem ent
|
1;
|
|
|
|
|
|
|
Statem ent
|
2;
|
|
|
}
|
r e tu r n
|
(value or
|
e x p r e s s io n ) ;
|
|
|
|
|
|
|
Лямбда-выражение для бинарной функции
|
507
|
Лямбда-выражение для бинарной функции
Бинарная функция получает два параметра и (не обязательно) возвращ ает значение.
Эквивалентное лямбда-выражение выглядит так:
[...](Typel& paramlName, Туре2& param2Name) { // здесь код лямбды; }
листинге 22.4 представлена лямбда-функция, перемножающая элемент за элементом два вектора равных размеров. Она использует алгоритм s t d : : tr a n s f o r m () и сохраняет результат в третьем векторе.
ЛИСТИНГ 22.4. Л ямбда-выраж ение как бинарная функция, перемножающая элементы двух контейнеров и сохраняющая результат в третьем_____________
#include
#include
#include
int main ()
{
using namespace std;
// Создание двух векторов целых чисел по 10 элементов каждый
vector vecMultiplicand, vecMultiplier;
10
// Вставить примеры значений от 0 до 9
for (int nCountl = 0; nCountl < 10; ++ nCountl)
vecMultiplicand.push_back (nCountl);
14
// Вставить примеры значений от 100 до 109
for (int nCount2 = 100; nCount2 < 110; ++ nCount2)
vecMultiplier,push_back (nCount2);
18
// Третий контейнер содержит результат умножения
vector vecResult;
21
// Создать пространство для результата умножения
vecResult.resize (10);
Do'stlaringiz bilan baham: |