-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathclosure.cpp
More file actions
160 lines (129 loc) · 5.07 KB
/
closure.cpp
File metadata and controls
160 lines (129 loc) · 5.07 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
#include <algorithm>
#include <iostream>
#include <vector>
struct EmptyStruct {};
bool call_int_predicate (bool (*pred) (int), int i) {
return pred (i);
}
int user_int () {
int i = 0;
std::cout << "int ? ";
std::cin >> i;
return i;
}
int main () {
std::cout << std::boolalpha;
auto vec = std::vector<int>{0, 1, 2, 3, 4, 5, 6};
// print_vec: print elements of a vector<int>
// Defined as a lambda which returns void (no return statement).
auto print_vec = [](const std::vector<int> & v) {
// Using std::for_each from algorithm
std::for_each (v.begin (), v.end (), [](int i) { std::cout << i << " "; });
// Note that global variables can be accessed in the lambda (std::cout is global)
};
std::cout << "Vec: ";
print_vec (vec);
std::cout << "\n";
#ifdef STATELESS
// Stateless lambda
auto is_zero = [](int i) { return i == 0; };
std::cout << "has_zero(v) = " << std::any_of (vec.begin (), vec.end (), is_zero) << "\n";
// Equivalent to EmptyStruct
std::cout << "sizeof (is_zero) = " << sizeof (is_zero) << "\n";
std::cout << "sizeof (EmptyStruct) = " << sizeof (EmptyStruct) << "\n";
// Casts to function pointer
std::cout << "call_pred (is_zero, 0) = " << call_int_predicate (is_zero, 0) << "\n";
std::cout << "call_pred (is_zero, 1) = " << call_int_predicate (is_zero, 1) << "\n";
// Error:
// std::cout << call_int_predicate(&is_zero, 0) << "\n";
#endif
#ifdef COPY_STATE
int tested_int = user_int ();
// has_tested_int(vec) ?
// auto is_tested_int = [](int i) { return i == tested_int; }; // Compilation error
auto is_tested_int = [tested_int](int i) { return i == tested_int; }; // tested_int in state
std::cout << "has_tested_int(v) = " << std::any_of (vec.begin (), vec.end (), is_tested_int)
<< "\n";
// Equivalent to int
std::cout << "sizeof (is_tested_int) = " << sizeof (is_tested_int) << "\n";
std::cout << "sizeof (int) = " << sizeof (int) << "\n";
// Does not cast to function pointer (compilation error)
// std::cout << "call_pred (is_tested_int, 0) = " << call_int_predicate (is_tested_int, 0) <<
// "\n";
// int has been copied, changing it does not impact the lambda copy:
tested_int = 0;
std::cout << "tested_int = 0; is_tested_int (0) = " << is_tested_int (0) << "\n";
#endif
#ifdef NESTING
// vec_has_int(i) ?
// -> define a lambda that calls std::any_of
auto vec_has_int = [vec](int i) {
return std::any_of (vec.begin (), vec.end (), [i](int k) { return i == k; });
};
std::cout << "vec_has_int (0) = " << vec_has_int (0) << "\n";
std::cout << "vec_has_int (42) = " << vec_has_int (42) << "\n";
// Vector has been copied in the lambda
std::cout << "sizeof (vec_has_int) = " << sizeof (vec_has_int) << "\n";
std::cout << "sizeof (vector<int>) = " << sizeof (std::vector<int>) << "\n";
// Deep copy is not affected by changes to original
vec[0] = 42;
std::cout << "vec_has_int (0) = " << vec_has_int (0) << "\n";
std::cout << "vec_has_int (42) = " << vec_has_int (42) << "\n";
#endif
#ifdef REF_STATE
// vec_has_int(i) without copy
// -> same lambda, take vec by reference (note the '&')
auto vec_has_int = [&vec](int i) {
return std::any_of (vec.begin (), vec.end (), [i](int k) { return i == k; });
};
std::cout << "vec_has_int (0) = " << vec_has_int (0) << "\n";
std::cout << "vec_has_int (42) = " << vec_has_int (42) << "\n";
// Only reference stored in lambda
std::cout << "sizeof (vec_has_int) = " << sizeof (vec_has_int) << "\n";
std::cout << "sizeof (vector<int>*) = " << sizeof (std::vector<int> *) << "\n";
// Can modify the lambda state then
vec[0] = 42;
std::cout << "vec_has_int (0) = " << vec_has_int (0) << "\n";
std::cout << "vec_has_int (42) = " << vec_has_int (42) << "\n";
#endif
#ifdef THIS_STATE
struct IntTester {
int i;
bool vec_has_int (const std::vector<int> & vec) const {
return std::any_of (vec.begin (), vec.end (), [this](int k) { return i == k; });
}
};
IntTester tester{4};
std::cout << "tester.vec_has_int " << tester.i << ": " << tester.vec_has_int (vec) << "\n";
tester.i = 42;
std::cout << "tester.vec_has_int " << tester.i << ": " << tester.vec_has_int (vec) << "\n";
#endif
#ifdef FUNCTIONAL
// A lambda can return a lambda
auto vec_has_int_factory = [](int tested_int) {
return [tested_int](const std::vector<int> & vec) {
return std::any_of (vec.begin (), vec.end (),
[tested_int](int i) { return i == tested_int; });
};
};
auto vec_has_0 = vec_has_int_factory (0);
auto vec_has_42 = vec_has_int_factory (42);
std::cout << "vec_has_" << 0 << ": " << vec_has_0 (vec) << "\n";
std::cout << "vec_has_" << 42 << ": " << vec_has_42 (vec) << "\n";
#endif
#ifdef AUTO_STATE
const int a = 42;
const int b = -333;
const int c = 55;
// Define a function using a lot of values
auto f = [a, b, c](int & i) { i = ((a * i) + b) * c; };
// auto f = [&](int & i) { i = ((a * i) + b) * c; }; // Take all external vars by reference
std::for_each (vec.begin (), vec.end (), f);
std::cout << "Vec f: ";
print_vec (vec);
std::cout << "\n";
// '=' captures all by copy, EXCEPT class members ! dangerous...
// auto f = [=](int & i) { i = ((a * i) + b) * c; };
#endif
return 0;
}