1 00:00:00,000 --> 00:00:02,392 (bright music) 2 00:00:02,392 --> 00:00:05,059 (keys clicking) 3 00:00:07,686 --> 00:00:08,970 Frank: In this video, we'll look 4 00:00:08,970 --> 00:00:11,550 at some of the motivating factors that led 5 00:00:11,550 --> 00:00:15,063 to the inclusion of lambda expressions in C++ 11. 6 00:00:16,379 --> 00:00:19,710 Lambdas were a tremendous addition to C++. 7 00:00:19,710 --> 00:00:23,580 Prior to C++ 11, we mainly used function objects 8 00:00:23,580 --> 00:00:26,550 and function pointers when we needed custom behavior 9 00:00:26,550 --> 00:00:28,320 with the standard template library, 10 00:00:28,320 --> 00:00:30,420 and also with our own code. 11 00:00:30,420 --> 00:00:31,980 Function objects were used mostly 12 00:00:31,980 --> 00:00:33,870 with the standard template library, 13 00:00:33,870 --> 00:00:37,320 and function pointers were used more often as callbacks. 14 00:00:37,320 --> 00:00:39,150 Okay, so what's the problem? 15 00:00:39,150 --> 00:00:41,700 Well, one of the problems is that we often ended up writing 16 00:00:41,700 --> 00:00:45,750 many short functions that control algorithms. 17 00:00:45,750 --> 00:00:47,850 And in the case of the STL, 18 00:00:47,850 --> 00:00:49,770 these small functions were encapsulated 19 00:00:49,770 --> 00:00:52,770 in small classes to produce function objects. 20 00:00:52,770 --> 00:00:55,566 Now, that's okay and it works, but many times the classes 21 00:00:55,566 --> 00:00:58,350 and the functions are defined far away 22 00:00:58,350 --> 00:01:00,960 from when they're used, and this can lead to problems 23 00:01:00,960 --> 00:01:04,170 with modifying, maintaining, and testing our code. 24 00:01:04,170 --> 00:01:07,230 In addition, the compiler's not so good at optimizing 25 00:01:07,230 --> 00:01:10,080 the functions when they're not defined in line. 26 00:01:10,080 --> 00:01:11,283 Let's see an example. 27 00:01:13,890 --> 00:01:15,600 In this example, we'll create a class 28 00:01:15,600 --> 00:01:18,390 that will serve to provide function objects. 29 00:01:18,390 --> 00:01:20,400 We'll see a couple of examples in these slides, 30 00:01:20,400 --> 00:01:22,680 as well as when we go to the IDE. 31 00:01:22,680 --> 00:01:25,980 Now, these classes all have the same type of structure. 32 00:01:25,980 --> 00:01:27,870 They might have attributes, constructors, 33 00:01:27,870 --> 00:01:30,450 and so forth, but the most important thing they have is 34 00:01:30,450 --> 00:01:33,270 an overloaded function call operator(). 35 00:01:33,270 --> 00:01:35,070 That's those open and closed parens 36 00:01:35,070 --> 00:01:36,870 that you see next to the operator(). 37 00:01:37,740 --> 00:01:39,960 You can see them in bold in the slide. 38 00:01:39,960 --> 00:01:42,870 Whenever this operator() is used, the function associated 39 00:01:42,870 --> 00:01:47,130 with it is called for an object of any Multiplier type. 40 00:01:47,130 --> 00:01:48,150 So in this example, 41 00:01:48,150 --> 00:01:51,139 we initialize Multiplier objects with an integer, 42 00:01:51,139 --> 00:01:52,980 and we store that in the num attribute. 43 00:01:52,980 --> 00:01:55,770 Then when we call the overloaded function operator 44 00:01:55,770 --> 00:01:57,690 with a Multiplier object, 45 00:01:57,690 --> 00:02:00,960 we multiply the passed in integer N by num, 46 00:02:00,960 --> 00:02:02,190 and we return the result. 47 00:02:02,190 --> 00:02:05,340 It's pretty simple, and these classes tend to be small, 48 00:02:05,340 --> 00:02:07,080 but depending on our application, 49 00:02:07,080 --> 00:02:09,870 we might end up with many variants of them. 50 00:02:09,870 --> 00:02:11,763 So how do you use these classes? 51 00:02:14,010 --> 00:02:16,113 Let's see an example with the STL. 52 00:02:17,400 --> 00:02:19,650 Let's assume that we have that Multiplier class 53 00:02:19,650 --> 00:02:23,070 that we just defined, and we have a vector called vec, 54 00:02:23,070 --> 00:02:24,450 which is a vector of integers, 55 00:02:24,450 --> 00:02:26,880 initialized to one, two, three and four. 56 00:02:26,880 --> 00:02:29,610 So let's create a function object from the Multiplier class. 57 00:02:29,610 --> 00:02:32,070 we'll call it mult, M-U-L-T. 58 00:02:32,070 --> 00:02:34,530 When we call the overloaded function call operator() 59 00:02:34,530 --> 00:02:37,650 on this object, it will return whatever integer we pass 60 00:02:37,650 --> 00:02:39,633 into it multiplied by 10. 61 00:02:40,770 --> 00:02:43,493 So we can call the STL algorithm transform, 62 00:02:43,493 --> 00:02:46,170 and provide the iterators for the vector. 63 00:02:46,170 --> 00:02:48,690 What this does is it starts at vec.begin() 64 00:02:48,690 --> 00:02:51,960 and ends at vec.end(), and it starts riding back 65 00:02:51,960 --> 00:02:54,780 or transforming the elements in vec from the beginning. 66 00:02:54,780 --> 00:02:58,110 That's it, but now what do we do to transform that vector? 67 00:02:58,110 --> 00:03:00,360 Well, that's where the function object comes in. 68 00:03:00,360 --> 00:03:01,920 We iterate through the vector, 69 00:03:01,920 --> 00:03:06,000 and we pass in each integer we see into mult. 70 00:03:06,000 --> 00:03:08,730 When we're done, vec now has been transformed 71 00:03:08,730 --> 00:03:11,103 to 10, 20, 30, and 40. 72 00:03:13,830 --> 00:03:16,530 Now, we don't have to create a named Multiplier object. 73 00:03:16,530 --> 00:03:19,170 We can simply create an unnamed Multiplier object, 74 00:03:19,170 --> 00:03:20,880 as you can see here in bold. 75 00:03:20,880 --> 00:03:22,530 We get the same behavior. 76 00:03:22,530 --> 00:03:23,970 So what's wrong with all of this? 77 00:03:23,970 --> 00:03:25,020 Well, nothing really. 78 00:03:25,020 --> 00:03:27,300 It just becomes tedious to write all these classes, 79 00:03:27,300 --> 00:03:29,190 each with a specific behavior 80 00:03:29,190 --> 00:03:31,500 in the overloaded function call operator(). 81 00:03:31,500 --> 00:03:33,660 And sometimes it's not so obvious what they're doing 82 00:03:33,660 --> 00:03:35,710 when you're looking at the existing code. 83 00:03:37,830 --> 00:03:40,380 Here's another example using a template class 84 00:03:40,380 --> 00:03:42,323 to create a generic Displayer, 85 00:03:42,323 --> 00:03:45,600 and we can use this with function objects of any type 86 00:03:45,600 --> 00:03:48,030 that overload the insertion operator(). 87 00:03:48,030 --> 00:03:50,070 Notice that we have no attributes in this class. 88 00:03:50,070 --> 00:03:52,920 All we're doing is overloading the function call operator() 89 00:03:52,920 --> 00:03:56,250 to display a T object to C out. 90 00:03:56,250 --> 00:03:58,230 So how can we use this class template? 91 00:03:58,230 --> 00:03:59,583 It's actually pretty easy. 92 00:04:01,560 --> 00:04:03,210 Let's create two functional objects 93 00:04:03,210 --> 00:04:05,010 from the Displayer template class. 94 00:04:05,010 --> 00:04:08,130 The first will display integers, and we'll call it D1, 95 00:04:08,130 --> 00:04:10,290 and the second will display std::strings, 96 00:04:10,290 --> 00:04:12,300 and we'll call it D2. 97 00:04:12,300 --> 00:04:15,840 Notice how we provide the type and the template parameters. 98 00:04:15,840 --> 00:04:17,820 We can now use these function objects 99 00:04:17,820 --> 00:04:19,620 just as we would use functions. 100 00:04:19,620 --> 00:04:22,680 We can call D1 and pass in 100 as an argument, 101 00:04:22,680 --> 00:04:25,773 and we can call D2 with Frank as the argument. 102 00:04:26,610 --> 00:04:27,510 Behind the scenes, 103 00:04:27,510 --> 00:04:30,060 the overloaded function call operator() is called, 104 00:04:30,060 --> 00:04:32,190 and we display the appropriate result. 105 00:04:32,190 --> 00:04:34,260 Now, this example really shows clearly 106 00:04:34,260 --> 00:04:36,510 that D1 and D2 are objects, 107 00:04:36,510 --> 00:04:38,340 but we're using them like functions, 108 00:04:38,340 --> 00:04:40,890 and that's the reason they're called function objects. 109 00:04:40,890 --> 00:04:43,590 But using them as in this example isn't all that useful, 110 00:04:43,590 --> 00:04:44,890 so let's see a better way. 111 00:04:47,910 --> 00:04:50,070 In this example, we have vec1 is a vector 112 00:04:50,070 --> 00:04:52,650 of the integers one, two, three, four, and five, 113 00:04:52,650 --> 00:04:56,193 and vec2 is a vector of strings, Larry, Moe, and Curly. 114 00:04:57,420 --> 00:04:59,610 Now we use std::for_each to display 115 00:04:59,610 --> 00:05:02,070 each of the elements provided by the iterators. 116 00:05:02,070 --> 00:05:03,510 In the first example, 117 00:05:03,510 --> 00:05:07,230 we instantiate a Displayer of int anonymously. 118 00:05:07,230 --> 00:05:09,300 Notice the function call operator() at the end. 119 00:05:09,300 --> 00:05:12,630 That's important, because we need to instantiate an object. 120 00:05:12,630 --> 00:05:15,060 In the second example, we used D1, 121 00:05:15,060 --> 00:05:17,160 which we created in the previous slide, 122 00:05:17,160 --> 00:05:19,323 and in the last example we used D2. 123 00:05:20,190 --> 00:05:22,590 So now these function objects display all the elements 124 00:05:22,590 --> 00:05:25,830 in the vector, and we only had to write the class once, 125 00:05:25,830 --> 00:05:27,870 since we wrote it as a generic template. 126 00:05:27,870 --> 00:05:29,730 That's pretty cool and it works great, 127 00:05:29,730 --> 00:05:32,400 but I think using lambda expressions is even cooler. 128 00:05:32,400 --> 00:05:34,200 Lemme show you what that looks like. 129 00:05:36,870 --> 00:05:38,610 Okay, so now let's do the same thing 130 00:05:38,610 --> 00:05:40,620 with lambda expressions. 131 00:05:40,620 --> 00:05:43,620 Note that all the code we need to do this is on this slide. 132 00:05:43,620 --> 00:05:45,060 We don't need anything else. 133 00:05:45,060 --> 00:05:47,520 We don't need that to Displayer template class 134 00:05:47,520 --> 00:05:50,113 or the function objects D1 and D2. 135 00:05:51,120 --> 00:05:54,480 We do have the same two vectors, vec1 and vec2. 136 00:05:54,480 --> 00:05:57,226 Now in the for_each, we don't pass in a function object. 137 00:05:57,226 --> 00:06:00,210 Instead, we use a lambda expression. 138 00:06:00,210 --> 00:06:01,206 Don't worry about the syntax 139 00:06:01,206 --> 00:06:03,000 of the lambda expression right now. 140 00:06:03,000 --> 00:06:06,150 We'll go over that in detail soon, but do notice 141 00:06:06,150 --> 00:06:09,420 that all the behavior we want is exactly where we want it, 142 00:06:09,420 --> 00:06:12,240 right in line in the call to for_each. 143 00:06:12,240 --> 00:06:14,940 So in this case, we're just displaying the data, 144 00:06:14,940 --> 00:06:16,800 but we can easily modify our lambdas 145 00:06:16,800 --> 00:06:19,020 to do whatever we want them to. 146 00:06:19,020 --> 00:06:20,490 This makes the code more readable, 147 00:06:20,490 --> 00:06:24,300 easier to test, easier to debug, and more maintainable. 148 00:06:24,300 --> 00:06:27,603 Also, the compiler can more easily optimize this code. 149 00:06:28,820 --> 00:06:31,800 Okay, so lambdas replace function objects, right? 150 00:06:31,800 --> 00:06:35,190 Yes, and we write less code and more focused code, right? 151 00:06:35,190 --> 00:06:39,060 Yes, so we never have to use function objects again, right? 152 00:06:39,060 --> 00:06:40,140 Wrong. 153 00:06:40,140 --> 00:06:42,985 Best practice with lambda expressions is to use them 154 00:06:42,985 --> 00:06:46,860 when the amount of code is a statement or a few statements. 155 00:06:46,860 --> 00:06:48,780 If you have more complex code, 156 00:06:48,780 --> 00:06:51,153 you should consider using a function object. 157 00:06:52,350 --> 00:06:54,990 One other benefit of a lambda expression is 158 00:06:54,990 --> 00:06:57,270 that the compiler creates a closure object 159 00:06:57,270 --> 00:06:59,100 from the lambda expression. 160 00:06:59,100 --> 00:07:00,870 This means that we can gain access 161 00:07:00,870 --> 00:07:03,720 to the environment in which the lambda exists. 162 00:07:03,720 --> 00:07:05,040 This is super powerful, 163 00:07:05,040 --> 00:07:07,440 and we'll see how it works pretty soon. 164 00:07:07,440 --> 00:07:10,140 So why did I spend time talking about function objects 165 00:07:10,140 --> 00:07:12,690 if we can mostly replace them with lambdas? 166 00:07:12,690 --> 00:07:14,555 Well, it's because the compiler generates 167 00:07:14,555 --> 00:07:17,880 unnamed function objects behind the scenes 168 00:07:17,880 --> 00:07:19,770 from the lambda expressions, 169 00:07:19,770 --> 00:07:22,050 and now you understand how they work. 170 00:07:22,050 --> 00:07:23,760 Great, so let's head over to the IDE, 171 00:07:23,760 --> 00:07:25,710 and we'll see some of this in LiveCode. 172 00:07:26,580 --> 00:07:28,020 Okay, so I'm back in the IDE. 173 00:07:28,020 --> 00:07:30,480 I'm in the section 21 Workspace, 174 00:07:30,480 --> 00:07:32,913 and I'm in the FunctionObjects project. 175 00:07:33,900 --> 00:07:35,250 And this project does a little bit 176 00:07:35,250 --> 00:07:36,840 of what we just did on the slides. 177 00:07:36,840 --> 00:07:38,100 It's really straightforward, 178 00:07:38,100 --> 00:07:39,540 but I really wanna go over it to make sure 179 00:07:39,540 --> 00:07:41,940 that you understand function objects. 180 00:07:41,940 --> 00:07:44,160 Function objects, I've seen a lot 181 00:07:44,160 --> 00:07:47,790 of beginning C++ programmers really not understand these, 182 00:07:47,790 --> 00:07:49,740 and I think it's all about that operator(), 183 00:07:49,740 --> 00:07:52,290 that function call operator() right here. 184 00:07:52,290 --> 00:07:53,123 I don't know why. 185 00:07:53,123 --> 00:07:54,000 It's just an operator(). 186 00:07:54,000 --> 00:07:55,320 Just 'cause it looks like a function, 187 00:07:55,320 --> 00:07:56,280 don't let it freak you out. 188 00:07:56,280 --> 00:07:58,770 It's just an operator(), just like the insertion 189 00:07:58,770 --> 00:08:01,500 or the extraction or a plus or a minus, that's it. 190 00:08:01,500 --> 00:08:03,420 It's just the way it's used is a little different, 191 00:08:03,420 --> 00:08:05,460 but it should be very, very straightforward, 192 00:08:05,460 --> 00:08:08,700 and hopefully, intuitive after this demo here. 193 00:08:08,700 --> 00:08:13,140 Okay, so what we've got here is we've got three classes. 194 00:08:13,140 --> 00:08:14,520 These two are structures. 195 00:08:14,520 --> 00:08:16,230 This one down here is a class, Multiplier, 196 00:08:16,230 --> 00:08:17,460 which I'll get to in a second. 197 00:08:17,460 --> 00:08:19,170 I'll just keep it closed for now. 198 00:08:19,170 --> 00:08:21,570 So what I'm doing here is I'm creating 199 00:08:21,570 --> 00:08:23,520 this structure right here. 200 00:08:23,520 --> 00:08:26,730 It's called Square_Functor, and all it does is 201 00:08:26,730 --> 00:08:29,580 that it overloads the function call operator() right there. 202 00:08:29,580 --> 00:08:31,451 That's it, that's all it's doing. 203 00:08:31,451 --> 00:08:34,890 By doing that, you cannot create function objects, 204 00:08:34,890 --> 00:08:37,230 and I'll show you exactly how that works in a second. 205 00:08:37,230 --> 00:08:39,330 So I'm overloading that operator(), 206 00:08:39,330 --> 00:08:43,230 and it expects an integer, and when I get that integer, 207 00:08:43,230 --> 00:08:45,450 I'm simply displaying the square, that's it. 208 00:08:45,450 --> 00:08:48,870 I'm not changing anything, I'm only displaying output only. 209 00:08:48,870 --> 00:08:50,790 Okay, so that one's straightforward. 210 00:08:50,790 --> 00:08:53,012 And then I've got a template class here 211 00:08:53,012 --> 00:08:56,070 that expects my template parameter T, 212 00:08:56,070 --> 00:08:58,950 and in this case, it's called Displayer. 213 00:08:58,950 --> 00:09:01,740 Again I'm overloading that operator(), right? 214 00:09:01,740 --> 00:09:03,360 The function call operator(). 215 00:09:03,360 --> 00:09:05,400 It expects a T, whatever that is, 216 00:09:05,400 --> 00:09:06,630 it could be an int, it could be a string, 217 00:09:06,630 --> 00:09:08,190 it could be just about anything, 218 00:09:08,190 --> 00:09:11,250 and all I'm doing again is outputting the data. 219 00:09:11,250 --> 00:09:12,270 So in this case, 220 00:09:12,270 --> 00:09:13,926 we have to make sure that we are overloading 221 00:09:13,926 --> 00:09:18,120 that insertion operator() with whatever type we're using. 222 00:09:18,120 --> 00:09:19,710 I'm only gonna be using ints and strings, 223 00:09:19,710 --> 00:09:21,900 so I know it's gonna work just fine with them. 224 00:09:21,900 --> 00:09:23,370 Okay, so let's go over main. 225 00:09:23,370 --> 00:09:24,960 Here is my test one. 226 00:09:24,960 --> 00:09:28,170 You can see the output right up here on the right. 227 00:09:28,170 --> 00:09:30,960 And what I'm doing is I'm creating an object, 228 00:09:30,960 --> 00:09:33,330 and that object's name is square. 229 00:09:33,330 --> 00:09:34,860 It's type is Square_Functor. 230 00:09:34,860 --> 00:09:36,990 It's one of these guys, right? 231 00:09:36,990 --> 00:09:37,823 The only thing I can do 232 00:09:37,823 --> 00:09:40,530 with that object is call its function call operator(). 233 00:09:40,530 --> 00:09:41,910 That's it, there's nothing else to do. 234 00:09:41,910 --> 00:09:44,520 There's no attributes, there's no other methods. 235 00:09:44,520 --> 00:09:46,590 So this is about as simple a function object 236 00:09:46,590 --> 00:09:47,610 as you can get. 237 00:09:47,610 --> 00:09:49,350 So now once I have square, 238 00:09:49,350 --> 00:09:52,620 I can say square and pass in a four. 239 00:09:52,620 --> 00:09:55,830 Now, this looks exactly like a function call, doesn't it? 240 00:09:55,830 --> 00:09:57,780 And that's the whole point. 241 00:09:57,780 --> 00:09:59,820 What's really happening behind the scenes is, 242 00:09:59,820 --> 00:10:02,550 remember, this square is not a function, it's an object. 243 00:10:02,550 --> 00:10:04,350 So what's really happening behind the scenes is 244 00:10:04,350 --> 00:10:08,610 that we're calling squares.operator() function call, 245 00:10:08,610 --> 00:10:10,083 and I'm passing in the four. 246 00:10:11,280 --> 00:10:12,300 Okay, hopefully that's clear. 247 00:10:12,300 --> 00:10:13,133 It's really important 248 00:10:13,133 --> 00:10:14,520 that you understand this piece right here. 249 00:10:14,520 --> 00:10:17,730 This is about as simple an example as I can come up with, 250 00:10:17,730 --> 00:10:20,490 because remember, lambdas are converted 251 00:10:20,490 --> 00:10:23,100 into these function objects behind the scenes. 252 00:10:23,100 --> 00:10:24,900 So in this case, we display a 16, 253 00:10:24,900 --> 00:10:27,810 and you can see the 16 displaying right here. 254 00:10:27,810 --> 00:10:30,780 In this case, I'm creating two function objects. 255 00:10:30,780 --> 00:10:33,240 One is called D1, the other one is called D2. 256 00:10:33,240 --> 00:10:35,610 I'm using this template class to do it, 257 00:10:35,610 --> 00:10:37,680 so I need to pass in my template parameter. 258 00:10:37,680 --> 00:10:40,490 So this one, D1 will display ints. 259 00:10:40,490 --> 00:10:42,840 D2 will display std::strings. 260 00:10:42,840 --> 00:10:44,640 All we're really doing here is outputting the data, 261 00:10:44,640 --> 00:10:45,930 so it's gonna be really simple. 262 00:10:45,930 --> 00:10:49,170 We call D1 with 100, D2 with Frank, 263 00:10:49,170 --> 00:10:51,780 and we get right out here, 100 and Frank. 264 00:10:51,780 --> 00:10:54,570 Again these guys look just like function calls, right? 265 00:10:54,570 --> 00:10:55,403 But they're not. 266 00:10:55,403 --> 00:10:56,580 They're function objects. 267 00:10:56,580 --> 00:10:59,070 What's happening is D1.operator(), 268 00:10:59,070 --> 00:11:01,290 function call operator() 100, 269 00:11:01,290 --> 00:11:04,470 D2.operator() using the function call operator(). 270 00:11:04,470 --> 00:11:06,810 Again we're passing in the string, okay? 271 00:11:06,810 --> 00:11:09,600 So again that's about as simple an example 272 00:11:09,600 --> 00:11:10,470 as I can come up with 273 00:11:10,470 --> 00:11:12,360 that really drives home the point here. 274 00:11:12,360 --> 00:11:14,220 They look like function calls, they're not, 275 00:11:14,220 --> 00:11:15,870 they're function objects. 276 00:11:15,870 --> 00:11:18,033 All right, so let's move on to test two. 277 00:11:19,650 --> 00:11:22,170 And what we'll do here is we'll use these function objects 278 00:11:22,170 --> 00:11:25,530 with our standard template algorithms. 279 00:11:25,530 --> 00:11:27,357 So here is my test two right here, 280 00:11:27,357 --> 00:11:31,020 and you can see the output beginning up here on the right. 281 00:11:31,020 --> 00:11:33,900 All I'm doing is creating vec1 as an integer vector, 282 00:11:33,900 --> 00:11:35,550 one, two, three, four, five, 283 00:11:35,550 --> 00:11:38,190 and vec2 is a vector of std::strings, 284 00:11:38,190 --> 00:11:39,120 Larry, Moe, and Curly. 285 00:11:39,120 --> 00:11:40,680 That's what we're gonna work with. 286 00:11:40,680 --> 00:11:42,420 And what we're gonna do now is we're gonna use 287 00:11:42,420 --> 00:11:45,093 the for_each algorithm right here. 288 00:11:45,990 --> 00:11:48,300 Remember it's an algorithm, so it needs an iterator. 289 00:11:48,300 --> 00:11:49,494 Here's the iterator. 290 00:11:49,494 --> 00:11:51,600 I'm gonna go from the beginning to the end of vector one, 291 00:11:51,600 --> 00:11:54,822 that's 1, 2, 3, 4, 5, and at each iteration, 292 00:11:54,822 --> 00:11:58,800 the algorithm will pass in whatever the element is 293 00:11:58,800 --> 00:12:00,570 in that collection right in that container, 294 00:12:00,570 --> 00:12:03,630 which is an integer, it's gonna pass it into square. 295 00:12:03,630 --> 00:12:04,800 So just like we did here, 296 00:12:04,800 --> 00:12:07,260 that's what's gonna happen behind the scenes. 297 00:12:07,260 --> 00:12:09,870 So it's gonna pass in the one, the two, the three, the four, 298 00:12:09,870 --> 00:12:11,730 and the five, in that order. 299 00:12:11,730 --> 00:12:14,190 And all we're doing with this _Functor right here, 300 00:12:14,190 --> 00:12:17,130 with this function object is displaying. 301 00:12:17,130 --> 00:12:19,710 So it's going to display the square of each of the numbers 302 00:12:19,710 --> 00:12:21,683 passed into it, one, four, nine, 16, 25. 303 00:12:21,683 --> 00:12:23,910 You can see the output right there. 304 00:12:23,910 --> 00:12:25,620 This does not change the vector, 305 00:12:25,620 --> 00:12:28,140 we're only displaying the vector. 306 00:12:28,140 --> 00:12:31,740 Okay, so here we're gonna display what we just did, 307 00:12:31,740 --> 00:12:34,353 and actually, this one is that guy right there. 308 00:12:35,193 --> 00:12:37,050 There's no display right there. 309 00:12:37,050 --> 00:12:40,080 So here, for_each again vec1 begin 310 00:12:40,080 --> 00:12:43,150 to vec1 data and call D1, what's D1? 311 00:12:43,150 --> 00:12:44,490 Well, D1 is that Displayer. 312 00:12:44,490 --> 00:12:47,280 All it does is output the value passed into it, 313 00:12:47,280 --> 00:12:49,770 so it's going to be passed in 1, 2, 3, 4, 5, 314 00:12:49,770 --> 00:12:52,050 and it's gonna display them right here. 315 00:12:52,050 --> 00:12:53,400 You can see it right there. 316 00:12:54,570 --> 00:12:57,390 In this case, little bit different, 317 00:12:57,390 --> 00:12:59,310 what I'm doing is I'm using the for_each, and here, 318 00:12:59,310 --> 00:13:01,890 I'm using vector two, which is Larry, Moe, and Curly. 319 00:13:01,890 --> 00:13:03,810 I'm going from the beginning to the end, 320 00:13:03,810 --> 00:13:07,680 and I'm creating a Displayer object right there. 321 00:13:07,680 --> 00:13:08,700 I'm doing that in place. 322 00:13:08,700 --> 00:13:10,764 I'm not naming it like I did D1 D2, 323 00:13:10,764 --> 00:13:12,905 so I'm just calling Displayer 324 00:13:12,905 --> 00:13:15,660 I'm using the template parameter std::string, 325 00:13:15,660 --> 00:13:16,770 and notice right here, 326 00:13:16,770 --> 00:13:19,470 those are important because that's what instantiates it. 327 00:13:19,470 --> 00:13:21,240 That's not the function call operator(), 328 00:13:21,240 --> 00:13:24,570 that's a constructor, so that's creating that object. 329 00:13:24,570 --> 00:13:27,810 So now I've got a Displayer object that can display strings. 330 00:13:27,810 --> 00:13:30,030 I'll loop through the vector using the algorithm. 331 00:13:30,030 --> 00:13:32,040 Every time it's gonna pass in an integer, 332 00:13:32,040 --> 00:13:35,441 and it's going to display Larry, Moe, and Curly. 333 00:13:35,441 --> 00:13:36,691 Okay, that's right there. 334 00:13:38,070 --> 00:13:40,290 And then down here, we're doing the same thing, 335 00:13:40,290 --> 00:13:42,690 except we're using the D2 function objects, 336 00:13:42,690 --> 00:13:44,550 which is the one we created earlier, 337 00:13:44,550 --> 00:13:46,140 and it does exactly the same thing. 338 00:13:46,140 --> 00:13:48,780 It just prints out Larry, Moe, and Curly. 339 00:13:48,780 --> 00:13:51,483 So now let's go on to test three. 340 00:13:53,310 --> 00:13:56,253 And we're right here on line 62. 341 00:13:57,690 --> 00:13:59,340 So what we're doing again now, 342 00:13:59,340 --> 00:14:00,750 this time we're gonna use lambdas. 343 00:14:00,750 --> 00:14:02,760 So all the stuff we just wrote up top, 344 00:14:02,760 --> 00:14:05,547 all those template classes and that Square_Functor, 345 00:14:05,547 --> 00:14:07,740 and all that stuff, we're not using any of that now. 346 00:14:07,740 --> 00:14:09,510 We're doing it all using lambdas, 347 00:14:09,510 --> 00:14:13,560 so this code right here is all self-contained. 348 00:14:13,560 --> 00:14:15,990 It needs nothing else, which is kind of cool. 349 00:14:15,990 --> 00:14:17,760 So right here, we're using for_each, 350 00:14:17,760 --> 00:14:21,930 and we're going from vector one beginning, vector one end. 351 00:14:21,930 --> 00:14:23,580 And here's my lambda expression, 352 00:14:23,580 --> 00:14:26,070 it starts here with those square brackets like that. 353 00:14:26,070 --> 00:14:27,447 We'll get used to that syntax in a second, 354 00:14:27,447 --> 00:14:30,960 and I'll talk about the syntax in detail in the next video. 355 00:14:30,960 --> 00:14:32,760 I just wanted to show you what it looked like. 356 00:14:32,760 --> 00:14:34,650 And lambda ends right there. 357 00:14:34,650 --> 00:14:36,090 So now what's gonna happen is 358 00:14:36,090 --> 00:14:40,200 the for_each algorithm will send in an integer right in here 359 00:14:40,200 --> 00:14:41,610 to the lambda, and it's X. 360 00:14:41,610 --> 00:14:44,010 And all we're doing is just displaying X squared. 361 00:14:44,010 --> 00:14:46,800 We're not changing X, we're not changing the vector, 362 00:14:46,800 --> 00:14:48,210 we're simply displaying the elements. 363 00:14:48,210 --> 00:14:50,760 The same thing we did with the Displayer. 364 00:14:50,760 --> 00:14:52,560 Okay, so that's it. 365 00:14:52,560 --> 00:14:54,120 What's gonna happen is it's going to print 366 00:14:54,120 --> 00:14:56,250 out one, four, nine, 16, 25, 367 00:14:56,250 --> 00:14:58,893 and you can see that right here in test three. 368 00:14:59,790 --> 00:15:02,400 Remember, we haven't changed the vector. 369 00:15:02,400 --> 00:15:04,980 Now, if we wanted to take each one of those integers 370 00:15:04,980 --> 00:15:06,930 that's being passed into the lambda 371 00:15:06,930 --> 00:15:09,990 and multiply it by 10, we could just do that right there. 372 00:15:09,990 --> 00:15:12,420 So hopefully, you can see how clear this is. 373 00:15:12,420 --> 00:15:14,310 It may not be clear the first time you see it. 374 00:15:14,310 --> 00:15:16,080 I remember the first time I saw lambdas, 375 00:15:16,080 --> 00:15:18,450 and I've used them in other languages as well. 376 00:15:18,450 --> 00:15:20,850 The syntax is always a little tricky at the beginning, 377 00:15:20,850 --> 00:15:23,010 but after a little bit, it becomes second nature. 378 00:15:23,010 --> 00:15:25,380 So what's gonna happen is the for_each will pass 379 00:15:25,380 --> 00:15:28,620 in each integer as X to the lambda expression, 380 00:15:28,620 --> 00:15:31,230 and all this lambda expression is doing is multiplying it 381 00:15:31,230 --> 00:15:33,000 by 10 and displaying it, that's it. 382 00:15:33,000 --> 00:15:34,140 It's not changing anything, 383 00:15:34,140 --> 00:15:36,630 it's just multiplying it by 10 and displaying it. 384 00:15:36,630 --> 00:15:40,200 So in this case, we're gonna get 10, 20, 30, 40 and 50. 385 00:15:40,200 --> 00:15:42,750 Here, we're just displaying X. 386 00:15:42,750 --> 00:15:45,180 And you can see how we're displaying 1, 2, 3, 4, and five, 387 00:15:45,180 --> 00:15:47,787 which tells you that that vector was never changed, 388 00:15:47,787 --> 00:15:49,237 and that was the whole point. 389 00:15:50,190 --> 00:15:53,340 And then the last example, we're using vec2 now, 390 00:15:53,340 --> 00:15:55,590 which is a vector of std::strings. 391 00:15:55,590 --> 00:15:57,420 Notice the parameter that's being passed 392 00:15:57,420 --> 00:16:00,540 into the lambda is a std::string now instead of an int. 393 00:16:00,540 --> 00:16:03,120 We did the int up here, we did the std::string here. 394 00:16:03,120 --> 00:16:04,260 This is really nice 395 00:16:04,260 --> 00:16:07,050 that you can code what you want right in here. 396 00:16:07,050 --> 00:16:08,276 This is what I want to do. 397 00:16:08,276 --> 00:16:11,310 I'm coding it right in there, that's all I need to do. 398 00:16:11,310 --> 00:16:13,050 I don't need to look through my source files 399 00:16:13,050 --> 00:16:16,500 to figure out where my my function object class is, 400 00:16:16,500 --> 00:16:17,333 or anything like that. 401 00:16:17,333 --> 00:16:20,880 It's right in here, right in place, which is kind of cool. 402 00:16:20,880 --> 00:16:23,040 In this case, I'm just displaying Larry, Moe, and Curly, 403 00:16:23,040 --> 00:16:24,690 and you can see them right there. 404 00:16:25,680 --> 00:16:27,540 All right, so now let's do the last one, 405 00:16:27,540 --> 00:16:29,010 and in order to do the last one, 406 00:16:29,010 --> 00:16:30,750 we're using this Multiplier class, 407 00:16:30,750 --> 00:16:32,850 so let me scroll up and I'll show you that. 408 00:16:32,850 --> 00:16:35,670 So this one's a little bit more complex, but not much. 409 00:16:35,670 --> 00:16:37,620 This is the same one we did on the slides. 410 00:16:37,620 --> 00:16:39,390 Here, I've got a class, 411 00:16:39,390 --> 00:16:42,423 and it's got a private attribute right here called num. 412 00:16:43,320 --> 00:16:45,240 It's got a constructor right here, 413 00:16:45,240 --> 00:16:48,090 you can see the user passes in an N, 414 00:16:48,090 --> 00:16:50,130 and all we're doing is assigning N 415 00:16:50,130 --> 00:16:52,680 to that attribute right there, that's it. 416 00:16:52,680 --> 00:16:54,357 We're just setting that instance variable. 417 00:16:54,357 --> 00:16:56,460 And notice right here, 418 00:16:56,460 --> 00:16:58,830 we're overloading the function call operator(). 419 00:16:58,830 --> 00:17:00,510 That's what makes it a function object 420 00:17:00,510 --> 00:17:03,420 when we create function objects from this class, okay? 421 00:17:03,420 --> 00:17:07,470 Best practice is when you've got variables 422 00:17:07,470 --> 00:17:09,329 or attributes in here and you don't want 'em changed, 423 00:17:09,329 --> 00:17:11,079 make sure you put constant in here. 424 00:17:11,940 --> 00:17:13,380 So that's it, so every time you call 425 00:17:13,380 --> 00:17:16,740 the function call operator() on Multiplier objects, 426 00:17:16,740 --> 00:17:19,095 it's going to take in whatever you pass in, which is N, 427 00:17:19,095 --> 00:17:22,020 and multiply it by whatever we set num to, 428 00:17:22,020 --> 00:17:23,369 that's all it's doing. 429 00:17:23,369 --> 00:17:25,710 So it's a real, real simple Multiplier. 430 00:17:25,710 --> 00:17:30,120 All right, so now let's go down to my test four right here. 431 00:17:30,120 --> 00:17:33,210 You can see right on line 75 is where it begins, 432 00:17:33,210 --> 00:17:35,310 and the output is right over here. 433 00:17:35,310 --> 00:17:38,940 I'm creating a function object right here called mult, 434 00:17:38,940 --> 00:17:40,920 and I'm passing in 100 to it. 435 00:17:40,920 --> 00:17:45,330 So remember, I could just simply pass anything into that now 436 00:17:45,330 --> 00:17:46,590 using the function call operator(), 437 00:17:46,590 --> 00:17:49,320 and whatever I pass in, it's gonna multiply it by 100. 438 00:17:49,320 --> 00:17:51,000 If I wanted to multiply it by 30, 439 00:17:51,000 --> 00:17:53,250 I'd create another function object, mult1, 440 00:17:53,250 --> 00:17:55,527 and pass it a 30 to it, for example. 441 00:17:55,527 --> 00:17:57,030 Okay, so let's see what, how this works. 442 00:17:57,030 --> 00:18:00,150 I'm assigning 1, 2, 3, 4 to my vector one, 443 00:18:00,150 --> 00:18:02,730 and now I'm gonna use std::transform. 444 00:18:02,730 --> 00:18:05,100 Std::transform does change the vectors. 445 00:18:05,100 --> 00:18:06,480 It's a little bit different. 446 00:18:06,480 --> 00:18:09,510 I think we used it once or twice in the STL section, 447 00:18:09,510 --> 00:18:10,920 but I'll go over it real quick. 448 00:18:10,920 --> 00:18:12,300 So here's std:transform. 449 00:18:12,300 --> 00:18:15,300 It wants where to start, where to end, 450 00:18:15,300 --> 00:18:16,830 and where to start making changes. 451 00:18:16,830 --> 00:18:18,960 That's why you have these three iterators here. 452 00:18:18,960 --> 00:18:20,340 So we have where to start. 453 00:18:20,340 --> 00:18:22,950 I'm gonna start at vector one begin. 454 00:18:22,950 --> 00:18:25,620 I'm going to end at vector one's end. 455 00:18:25,620 --> 00:18:28,260 Basically, I'm gonna iterate through the entire vector one, 456 00:18:28,260 --> 00:18:30,840 which is again, 1, 2, 3, 4, 457 00:18:30,840 --> 00:18:33,505 and I'm gonna start making changes in vec1 begin. 458 00:18:33,505 --> 00:18:35,089 So it's gonna start making changes here 459 00:18:35,089 --> 00:18:36,960 and here and here and here, it's gonna change all of them. 460 00:18:36,960 --> 00:18:37,920 And what's it changing? 461 00:18:37,920 --> 00:18:41,040 Well, it's using that object. 462 00:18:41,040 --> 00:18:43,860 So what's gonna happen is it's gonna go through vec1, 463 00:18:43,860 --> 00:18:46,590 it's gonna grab the one, and it's gonna pass it into mult. 464 00:18:46,590 --> 00:18:47,790 What's mult gonna do? 465 00:18:47,790 --> 00:18:50,670 It's gonna take that guy and multiply it by 100, 466 00:18:50,670 --> 00:18:53,940 and it's gonna stick it back into vector one's position, 467 00:18:53,940 --> 00:18:55,020 so it's gonna make that 100. 468 00:18:55,020 --> 00:18:57,960 It's actually going to transform the vector, right? 469 00:18:57,960 --> 00:18:59,580 So when we're done with this, 470 00:18:59,580 --> 00:19:01,770 we're just going to display it, 471 00:19:01,770 --> 00:19:03,620 and you could see the display right here 472 00:19:03,620 --> 00:19:07,080 100, 200, 300, 400, it actually changed that vector. 473 00:19:07,080 --> 00:19:08,460 And then let's do it again. 474 00:19:08,460 --> 00:19:10,110 What we're doing here is we're resetting 475 00:19:10,110 --> 00:19:12,210 that vector one to 1, 2, 3, 4. 476 00:19:12,210 --> 00:19:14,190 I'm just assigning 1, 2, 3, 4 to it. 477 00:19:14,190 --> 00:19:15,311 And what we're gonna do now is 478 00:19:15,311 --> 00:19:16,740 we're gonna do exactly the same thing, 479 00:19:16,740 --> 00:19:19,110 except we're not gonna use the function object mult. 480 00:19:19,110 --> 00:19:20,640 We're just gonna do it in a lambda. 481 00:19:20,640 --> 00:19:21,933 Here's my lambda. 482 00:19:23,640 --> 00:19:27,180 I'm using std::transform again, starting at the beginning, 483 00:19:27,180 --> 00:19:29,130 going to the end of vec1, 484 00:19:29,130 --> 00:19:32,183 and start transforming from the beginning of vec1. 485 00:19:32,183 --> 00:19:34,890 So every time I get an integer, 486 00:19:34,890 --> 00:19:38,160 all I'm going to do is return that integer times 100, 487 00:19:38,160 --> 00:19:40,410 and it's gonna be stored back into that vector. 488 00:19:40,410 --> 00:19:42,120 It's gonna transform the vector. 489 00:19:42,120 --> 00:19:44,460 And now when I use my for_each again, 490 00:19:44,460 --> 00:19:46,260 and notice over here when we did the for_each, 491 00:19:46,260 --> 00:19:48,780 we used that Displayer function object. 492 00:19:48,780 --> 00:19:50,790 This time, we're using another lambda 493 00:19:50,790 --> 00:19:51,750 just to do the displaying. 494 00:19:51,750 --> 00:19:55,200 All we're doing is just outputting X, simple as that. 495 00:19:55,200 --> 00:19:57,900 And when we do that, you'll get exactly the same result, 496 00:19:57,900 --> 00:20:00,250 100, 200, 300, 400. 497 00:20:00,250 --> 00:20:01,680 Okay, so this gives you a little bit 498 00:20:01,680 --> 00:20:04,140 of a taste for function objects and lambdas. 499 00:20:04,140 --> 00:20:04,973 In the next video, 500 00:20:04,973 --> 00:20:07,710 what we'll do is we'll take this syntax right here, 501 00:20:07,710 --> 00:20:09,187 this is actually all you need to remember, 502 00:20:09,187 --> 00:20:11,133 square brackets, ta-da. 503 00:20:12,630 --> 00:20:15,330 That's it, that's the lambda, okay? 504 00:20:15,330 --> 00:20:17,198 And you can see the syntax. 505 00:20:17,198 --> 00:20:18,031 There's my capture list. 506 00:20:18,031 --> 00:20:19,230 This is where my parameters come in. 507 00:20:19,230 --> 00:20:20,476 There's my code. 508 00:20:20,476 --> 00:20:21,390 Now, there's a couple of other bits 509 00:20:21,390 --> 00:20:22,320 that you can throw in here. 510 00:20:22,320 --> 00:20:24,660 You can do that, and you can throw some keywords in there, 511 00:20:24,660 --> 00:20:26,342 and we'll talk about all of that in the next video 512 00:20:26,342 --> 00:20:27,900 when we go over the structure 513 00:20:27,900 --> 00:20:30,180 of the lambda expression in detail, 514 00:20:30,180 --> 00:20:31,280 so I'll see you there.