Hello again! In this video, we are going to look at the pair type.
I have just added a couple of videos at the end of this section, with some things that we need to know about
before we can go on and look at algorithms and containers in more detail.
The standard pair type is defined in the header.
It has two public data members, which are called "first" and "second".
They can be of different types.
And there are no public member functions.
So this is rather an unusual type.
I do not think there is anything else in the library which has a public data member.
One use for this is, if you have a function which returns two values, you can return a pair object instead
of having to define a struct.
There are some containers in the Standard Library which use a pair to store their elements.
So that is really why we are interested in it.
The pair is a templated type.
So when we call the constructor, we need to give the types of both the members.
If we are creating a pair which has "Hello" as the first member and "there" as the second member, then we
need to make this a pair of two strings.
And once that has been created, we can access
that, as "wordpair"
dot "first" is "Hello",
and "wordpair" dot "second" is "there".
Alternatively, we can call make_pair() to create the variable.
So we just give the first and second values as arguments, and the compiler can deduce the types from that.
So we need to put the "s" suffix in here, to make sure we get strings.
If we do not put that, then we will get arrays of char, which is different.
And then we are just using that to initialize a pair object, and we can use auto there. In C++17,
the compiler can deduce the types for a constructor call.
So we can just put the arguments, without having the angle brackets.
And again, we need to make sure we get the right types.
So let's try that out. We have our constructor call here, and then we print out the first and second
members.
And we get "hello" and "there".
We can also use make_pair() to create the object.
"hello" and "there".
And that is quite useful if you are returning from a function. You can just call make_pair() and then
put the data that you want to return.
And finally, you can use the C++17 form, which Visual C++ does not support.
So let's try GCC.
And yep, that does work.
So let's look at an example of a function which returns a pair.
So here is that function.
It actually calls the lambda expression we had in the earlier video, but this time we have taken
it into a separate function instead of putting it inside main().
So this function will take the vector as an argument.
And also the number of characters that we want the element to have. Then it will do this find_if() call.
And this will calculate the index of the first string with more than that many characters.
And then we can return the string and the index as a pair.
We dereference the iterator, after checking that
it is valid. If we do not get anything at all,
we just return an empty string and the index of minus one will tell the caller that there's nothing
there.
So this returns a pair. We are using list initialization here, which is yet another way to create a pair!
And then the main() function is all the same, except we have this call to the function, instead of calling
find_if() directly.
And there we are, we get "collection" and 1.
We can also get a bit more up to date and use some C++14 and 17 features. So we can get this function to
return auto instead of watching out the pair explicitly.
I think that is probably a bit marginal.
If we were turning an iterator as one of the elements, then that would be a good case.
But this is possibly - well, it is up to you, really.
And then we can use the C++ 17 constructor, which does not require the angle brackets.
And the same code again.
OK. Some of you might not be completely convinced by Modern C++. I mean, there is one or two nice things,
but there is nothing really wrong with the old way of doing things.
So I have written this out again, using C++ 03. Or 98, if you prefer, they are basically the same standard.
So we have to use the functor.
We have to write it out ourselves, because the compiler is not going to generate it for us.
That is just the one we had in the previous video.
Then we have to use this form of initialization, because brace initialization is not supported.
We have to write out the iterator type explicitly, because there is no "auto" keyword.
We have to use the memory function call to begin(), because there is no non-member function. And then
we can call make pair.
And then the - possibly the most painful bit or perhaps the iterator is the most painful, but
having to type all this completely unnecessary code, really, when you are used to writing list initializers.
Then again, we cannot use the auto keyword and we cannot use raw strings. Although maybe that is not a big
loss in this.
So you can see that some features are just slightly convenient. And some are very convenient!
And then obviously, that works.
Okay, so that is it for this video.
I will see you next time.
Until then, keep coding!