WEBVTT

00:00.120 --> 00:00.690
Hello again!

00:01.050 --> 00:03.360
In this video, we are going to look at tuples.

00:04.020 --> 00:07.350
Tuples in C++ are related to pairs.

00:07.350 --> 00:10.710
So let's first remind ourselves what those do.

00:12.360 --> 00:14.250
A pair is a compound type.

00:14.820 --> 00:19.110
It has two members, which we can access with the names first and second.

00:19.770 --> 00:21.480
These members can have any type.

00:22.320 --> 00:29.100
We can create a pair object explicitly, by giving the types of the elements as template parameters.

00:29.610 --> 00:32.790
So here we have a pair which has two members, of type string.

00:33.830 --> 00:37.410
Or we can use make_pair() to create the pair object, with auto.

00:37.860 --> 00:43.770
So in this case, the compiler will deduce that word_pair is a pair, whose members are both type string.

00:46.190 --> 00:49.550
In C++11, we have a tuple type in the library.

00:50.000 --> 00:51.680
It is defined in the <tuple> header.

00:52.430 --> 00:55.460
It is similar to the pair, but it can have any number of elements.

00:55.880 --> 00:59.090
The number of elements has to be fixed for a particular object.

01:00.470 --> 01:05.930
It is not really practical to use the names of members, so instead we use the index for accessing the

01:05.930 --> 01:06.380
elements.

01:07.870 --> 01:14.350
Again, we can create a tuple object explicitly, by giving the types of the members as template parameters.

01:15.120 --> 01:18.700
Or we can use make_tuple() and let the compiler deduce it for us.

01:22.360 --> 01:25.750
The way that we access tuple members is a bit peculiar.

01:26.320 --> 01:33.610
There is a non-member function, called get(). This takes the tuple as argumen. And then it has a template

01:33.670 --> 01:36.010
parameter, which is the index of the element.

01:36.880 --> 01:42.850
So if we call get() with parameter zero, that will be the first element. And then we pass the

01:42.850 --> 01:44.500
"numbers" tuple.

01:44.650 --> 01:48.160
So this will return the first element of the numbers tuple.

01:49.300 --> 01:51.790
And we can also assign to the return value from get().

01:52.990 --> 01:58.660
So we can actually use get() to set the value of an element. Which is perhaps rather confusing naming.

01:59.560 --> 02:02.470
But that is quite common in C++, I'm afraid.

02:03.430 --> 02:09.100
So in this case, we are getting the second element of numbers, and setting its value to three.

02:11.390 --> 02:12.770
In C++14,

02:12.770 --> 02:18.710
we can also use the type of the parameter, provided there is only one elements which has that type.

02:19.550 --> 02:26.330
So we can call get() with parameter int, and that will return the member of numbers which has type int.

02:28.650 --> 02:30.180
So let's try that out.

02:30.660 --> 02:32.280
We create our tuple.

02:32.760 --> 02:39.900
We pass the types of the elements as template parameters. Or we could also calle make_tuple().

02:41.730 --> 02:44.310
There is our call to get(), with parameter zero.

02:44.820 --> 02:47.730
So this is going to return the first element of this tuple.

02:48.990 --> 02:50.300
get() with parameter

02:50.310 --> 02:56.040
one will be the second member of this tuple. And then we can set that to three.

02:57.510 --> 03:04.320
If we have the parameter type of int, then this will return the member which has type int, which is this

03:04.320 --> 03:04.590
one.

03:05.220 --> 03:07.020
We just set that to three.

03:07.290 --> 03:10.080
So we would expect that this call will return three.

03:11.790 --> 03:12.390
And there we are.

03:13.830 --> 03:14.880
First elements is one.

03:15.270 --> 03:17.040
Second element, set to three.

03:18.630 --> 03:22.440
It is also possible to get all the elements of a tuple with a single call.

03:22.920 --> 03:26.130
There is a non-member function called tie() which does that.

03:26.670 --> 03:28.470
And again, this is a bit peculiar.

03:29.400 --> 03:33.140
We need to have some variables, which we are going to use to store the data.

03:33.750 --> 03:39.600
Then we pass those variables as arguments to tie(), and then we assign the result of calling tie().

03:39.900 --> 03:45.540
So this is going to extract all the elements from number, and then store the first element in "d", the

03:45.540 --> 03:49.290
second element in "i" and the third elements in "str".

03:49.980 --> 03:55.710
And obviously, the number and type of these variables must match the elements of the tuple.

03:58.010 --> 03:59.130
So let's try that out.

03:59.150 --> 04:00.560
We have the same tuple again.

04:01.340 --> 04:03.800
We have the variables, which we are going to populate.

04:04.460 --> 04:05.390
Then we call tie().

04:05.420 --> 04:11.360
We pass the variables. And then we assign this to the numbers tuple, and then we print out the result.

04:12.710 --> 04:13.340
So there we are.

04:13.340 --> 04:15.500
The tuple elements are one, two and three.

04:17.650 --> 04:20.290
So when would you want to use a tuple?

04:21.220 --> 04:27.340
One good example is, if you have some data, and you just want to stash it somewhere, without too much trouble.

04:28.090 --> 04:32.920
If you do not wants to write a class and think about member functions, special member functions and

04:32.920 --> 04:36.550
so on. And you are not actually going to use that type anywhere else.

04:37.240 --> 04:40.870
And this is especially useful if the data has elements of different types.

04:41.620 --> 04:45.130
Otherwise you could use a vector, or an array, or some other container.

04:47.380 --> 04:50.830
Another good example is returning multiple values from a function call.

04:51.370 --> 04:53.710
This is a question that I have been asked at interviews.

04:54.490 --> 04:59.050
If you have exactly two values, you could use a pair. But in the general case, you have to create

04:59.050 --> 04:59.530
a struct.

05:00.010 --> 05:02.290
Think up a unique name for it in that namespace.

05:02.770 --> 05:08.440
Then think of names for all the members, then populate all the members in the function body, and then

05:08.440 --> 05:09.070
in the caller.

05:09.340 --> 05:14.920
You have to copy all the data from the members of the struct into your own variables. Which is all

05:14.920 --> 05:15.580
a bit tedious.

05:17.020 --> 05:18.980
With the tuple, you can do it much more conveniently.

05:20.110 --> 05:25.840
You can have a function which returns a tuple, so you just make the parameters the right type for your

05:25.840 --> 05:26.240
data.

05:27.220 --> 05:30.730
You can use a list initializer for creating this tuple object.

05:31.180 --> 05:33.280
So you could do that with variables, as well as literals.

05:34.210 --> 05:40.270
And then, in the caller, you just call tie(). And then this will copy the data, from the returned tuple,

05:40.270 --> 05:41.200
into your variables.

05:42.770 --> 05:49.940
Unfortunately, we cannot use auto, at least not in C++14, because tie() is not able to deduce the types

05:49.940 --> 05:52.070
of the elements. It is just too difficult.

05:54.600 --> 05:55.620
So here is that code.

05:55.650 --> 05:58.110
Here is our function which returns a tuple.

05:58.800 --> 06:01.110
Then we create this tuple using the list

06:01.110 --> 06:01.740
initializer.

06:02.820 --> 06:09.960
Then we have the code which unpacks the tuple into these variables. And we unpack the tuple which was

06:09.960 --> 06:11.010
returned by the function.

06:11.400 --> 06:15.840
So this should give us the data from the function. And there we are.

06:16.440 --> 06:17.900
Okay, so that is it for this video.

06:18.270 --> 06:19.080
I will see you next time.

06:19.080 --> 06:21.360
But until then, keep coding!
