Okay.
Welcome back.
So let's continue with the examples of stateful lambdas in this case.
I mean, Test seven and you can see that I've scrolled that up right up here so you can see my test
seven right here.
This basically is equivalent to the last test six that we just did.
The difference is that rather than captured by value in one by reference, I'm capturing by reference
and two by value.
So it's just mixing things up.
So let's go through this here.
I'm saying capture everything by reference except X and Z, capture them by value.
So again, you can see it's exactly the same thing just done a little bit different syntactically.
We're going to capture everything by reference except X and z.
So X.
And Z will be copied.
They're going to be captured by value.
That's 103 hundred.
And everything else, which in this case is why will be captured by reference.
So there's my reference.
And again, we're going to increment everything by 100 and display everything just like we did before.
We should get the same output.
So I'm going to call my lambda x will be incremented by 100.
That's my local x right here.
Y will be incremented by 100 through this reference.
That's going to be 300.
Z will be incremented by 100.
So that'll be 400 right here.
And we're going to display X, Y and Z, which are 200, 304 hundred and just what we see.
Now, when I come back from the function, I'm going to display X, Y and Z again, we're going to display
these guys.
So that would be 100 and 303 hundred.
103 hundred and 300.
Okay.
Perfect.
So now let's do a few with some objects in test eight.
I've defined a person class that's really, really similar to the person class that I defined in the
previous stateless Lambda Demo.
So you can see what's happening here.
I've got my class person, I've overloaded the insertion operator to be a friend just to allow us to
display person objects real easily.
A person has a name and an age.
I've got a default constructor and you can use this syntax.
I didn't really talk about this much in the class, but it's just a handy way of telling the compiler,
hey compiler, generate a default constructor for me.
Sometimes it's real handy because you can actually be very explicit to tell whoever is reading your
code, whatever other programmers reading your code, that this is exactly what you intended.
So I've got an overloaded constructor here, a copy constructor here, and I've done the same thing,
a destructor here, and then I've got my jets and my sets and so forth.
Now you can see I've added three methods here, and let me just expand this so you can see what they're
doing.
There we go.
So in this case, I have a method called change person one and another one called change person two
in another one called change.
Person three they pretty much do exactly the same thing.
Notice that they return auto because we're returning a lambda and I just want the compiler to figure
out the syntax for me.
So in this case, what are we capturing?
We're capturing this which is the this pointer we're capturing by value or capturing by reference.
If you remember from the slides, these three things are equivalent.
They all captured by reference.
What I would like you to do is always use this version.
The version with the equal sign is deprecated in C++ 20.
That means it's not going to be supported going forward.
That's a good thing because when a programmer sees that they're thinking captured by value and that
doesn't happen here, what's happening is captured by reference.
So it can be confusing and it always has been confusing.
And this one, you know, why do it when we really want to capture the this pointer.
So I would encourage you to use that version only.
So look what this does.
I have I'm capturing this and the parameters being passed into this are the new name and the new age.
And all I'm doing is I'm setting name and age to new name and New Age respectively.
Notice that right here I don't have to say this name.
Right or this age right here.
The compiler will figure that out for us because of the syntax.
What other name could we be talking about?
It has to be these guys, so the compiler figures that out.
So what we're going to do is when we call these methods, the lambda will capture the this pointer and
modify those values.
Not a big deal.
Pretty straightforward, but I just wanted to show you how you could capture this.
And later on, we're going to do another example where we capture it another way.
So let's take a look at the test here.
And I'm only going to go over this one.
You can see all three of them.
There's three different examples here.
All three will give you the exact same output.
But in this case, look what we've got.
We've got person Larry 18.
So Larry is a person who's 18 years old.
So now this is what we're going to do.
We're going to capture using this, which is that one in person one.
So notice what I'm doing is I'm calling change person one in person a method call just like before.
Right.
But this guy is returning a lambda.
That's pretty cool.
So now that I've got my lambda right here, I can call, I can say change person one and pass in Moe
and 30.
Moe is going to be passed in four for the name and 30 for the age and they're going to change.
So when I display you're going to see something else display, right?
You're going to see instead of Larry, you're going to see Moe display.
Let me show you right here.
All right.
So remember, this is our first output statement right here.
It just displays Larry, it looks like that now we're calling change person one and then displaying
that value.
And in this case, we're displaying Moe.
And you can see here where I'm capturing by.
Value and by reference is changing to Curly and to Frank, because I'm passing in Curly and Frank.
So you can see that's a good example that shows how all three of these captures are equivalent.
But as I said, no stick to using the this capture.
That's what you're going to see out there.
I don't think you would ever see this out there.
I've never seen it out there, even though it's perfectly legal to use.
And I've seen this a few times.
But if you're capturing instance variables from an object, use this.
It's really, really clear what your intention is.
Okay, so that would be our test eight.
And let's take a look at this one here.
This is similar.
I've got a class called Lambda and it's got a private instance variable y.
You can see my constructor right here and there's my operator.
Does that look familiar?
It should look familiar, right.
Because that's exactly like the closure class that gets created from a lambda expression.
Remember that we've got our function call operator, we're passing in the X.
This is exactly like the example that we went over in the slides.
So let's take a look at the equivalence of a class like this versus a lambda expression.
They're the same.
Sometimes you'll see these instead of classes.
You'll see this as a struct and everything public.
But that's okay.
It works exactly the same way.
So let's test nine.
Let me scroll up a little bit.
All right.
So here's test nine.
I'm displaying the header there.
I've got Y, which is 100 and I've creating an instance of Lambda one and I'm passing in Y, which is
100 that is going to create this guy, it's going to call this constructor, it's going to initialize
this to 100, just like we would expect.
Now, when I call them to one, I'm passing the 200 here and it's going to add 102 hundred and display
300.
That's what's happening when we're using this class.
In this case, I've got a lambda variable lambda to notice what we're doing.
We're capturing y by value.
It's got a parameter X and it's displaying the sum of x and Y exactly the same thing.
When I call them the two with 200, you get exactly the same output.
So you can see that these two examples are equivalent.
That and that their equivalent.
This kind of code is what's being generated from that lambda expression.
And this is really important to understand because it really gives you a good insight into how these
lambdas work behind the scenes.
It's really nice to be able to use them, but it's even better to be able to understand how they work
behind the scenes.
All right.
So let's do one more and that would be test ten.
And for Test ten.
I've got a lot going on here, so let me walk through this really slowly.
In this example, I created a class called People and that people class has a bunch of person objects
in it, but it's got a stupid vector of persons.
So people consists of a bunch of person objects.
And then I've also got this instance variable right here called Max people.
Think of that as the maximum number of people that you will be able to display.
So if there's 100 person objects in this vector and I try to display them, I should only be allowed
to display ten or five or three or whatever this value is here and the constructor just sets this guy
to ten by default or gives it whatever value the user supplies.
I've got a copy constructor that I'm just defaulting and I think that's about it.
I don't need a destructor because there's no pointers or anything here.
Now I've got an add method.
And what that ADD method does is it allows me to add a person to my vector right here and I can pass
in the person's name and the person's age and I can use and place back, which creates a person object
from these values and pushes it back onto the people vector.
If you don't recall in place back, you can go back and look at the vectors lecture in the steel section.
Now I've got another method right here called Set Max people and the user passes in a number and we're
setting that instance variable to whatever they pass in and the getter as well.
Okay.
So now let's see how we can use a lambda with this.
Okay, so now I've got a method called get people and get people returns a vector of persons.
So basically what we're going to do is we're going to return all the person objects in that people class
whose age is greater than max age.
And I'm only going to return less than max people.
I'm not going to go over that value.
That's really important.
Now, the interesting thing here is when the user calls, get people the user really has no idea about
max people.
They're just sending it an age.
So I might have 100 people in this people vector that had that are over 50.
I'm only going to display ten of them because of that value.
Let's see how this works.
First thing I'm doing is I'm creating a local stood vector of persons called result.
It's empty right now and I've got to count.
Now I'm going to use the standard template library algorithm copy if.
And I'm going to copy matches to this result as long as they match the criteria that I mentioned.
So right here I'm going to say Stuart, copy if.
What are we copying from people.But begin?
Where are we copying up to?
People end so I'm using the entire people vector.
And what I'm going to do is when I've got a match I'm going to use stood back and solder which basically
pushes back whatever I'm getting into that result that vector that I'm building right here and obviously
what I'm getting is person's right.
So now it comes to Lambda, when do we actually do this copy if there's an if in there.
So it has to match something.
And let me expand this out so you can see all the code right here.
So look at what we're doing here.
First of all, we're capturing this.
That allows me access to that guy, which is an instance variable in this class as well as the vector
I'm capturing count by reference.
That's this guy right here because I need to modify that.
And I'm expecting a person reference that's constant and that's what copy if is going to give me.
Right now.
What's my predicate?
Well, my predicate basically says if ps h that's the object that's being passed into me is greater
than this max age and I'm going to pre increment count and make sure that it's less than or equal to
max people.
That's it.
That's pretty cool.
So you can see what we're using here.
We're using that lambda to gain access to the object.
And once we have access to the object, we can use all kinds of good stuff.
So at this point, we need that we need that access to the object to get to max people.
So now we're good at this point, we're going to return result and it's going to contain as many people
that match that criteria as I'm allowed to print.
Now, the idea here is, sure, this this function could have accepted the max number of people to print.
But suppose there are two entities here, one that is setting that policy and this one that's using
this and this function really shouldn't know about the other.
All right.
So let's run through a test here, see how all this works.
So here we are in Test ten, and I've got people, friends, and then I'm going to add Larry, Curly,
Moe, Frank and James.
Now I'm going to call get people.
Now, remember when I called this guy, the max was ten, so the most that I could display was ten.
That was the default parameter in my constructor.
When this function returns, I'm going to have a sorted vector of person objects.
That's what this is.
That contains all the people whose age is 17 or over.
Now, this is basically everybody you can see.
Everybody here is 17 or older, right?
So once I get that, I'm just going to loop through that result and display them all.
You can see right here, I'm getting them all.
Now I'm going to set the maximum number of people to three, and I'm going to call that function exactly
the same way.
Friends target people 17.
I'm still going to get five matches, right?
But I'm only going to get three back because the max is three.
Now, when I come over here and display this, I'm going to see very Curly and Moe only.
So now let's take a look at this last example here.
Remember, we've still got three is the max.
Not that it matters in this case, but in this case.
I want to get people over 50.
Well, the only person over 50 is James.
So all we get back is James.
Had there been 40 people that are over 50, I only would have gotten three of them back and displayed
only three.
This can be really handy sometimes.
You've got a game going on and you've got players.
You've got a whole bunch of players, but only a certain number of players meet a certain criteria and
there may be so many of them that you just want to randomly pick one, two or three or give you the
first three back or the first ten back, depending on what logic is running in the program.
Okay, so that's it.
Those are a bunch of examples for State Full Lambdas.
Hopefully the stuff makes sense.
There's a lot of other examples that obviously you can play around with and create yourself.
In the next video we'll wrap up this section and we'll go over some examples of using lambdas with the
standard template library algorithms, some simple use cases, and we'll just kind of pick a bunch of
example algorithms and try them out and show you how that works.