WEBVTT

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

00:00.960 --> 00:03.120
In this video, we are going to look at attributes.

00:04.590 --> 00:07.070
Compiler writers have various directives.

00:07.080 --> 00:12.810
These are things you can put in C++ source code, to make the compiler behave in various ways.

00:13.680 --> 00:19.080
These have names like hash pragma, double underscore attribute and double underscore declspec.

00:19.650 --> 00:21.570
These are not part of the C++ language.

00:22.080 --> 00:23.520
They are compiler specific.

00:25.740 --> 00:32.670
So these are used for things like: making the compiler generate certain types of code, laying out objects

00:32.670 --> 00:38.040
in memory in a certain way, using conventions for calling functions. And so on.

00:39.060 --> 00:45.960
C++11 introduced attributes, to provide a standard syntax for these compiler directives, and it also

00:45.960 --> 00:50.460
defined a few attributes in the language. Which we can use in our own programs.

00:52.120 --> 00:57.370
These attributes are meant to give extra information to the compiler. And they are not supposed to be

00:57.370 --> 01:00.670
used to extend the language, or change the meaning of programs.

01:01.300 --> 01:06.580
So they are nothing like Java attributes, which you can use for things like implementing database support.

01:09.120 --> 01:15.480
The syntax for an attribute is that we use a pair of double square brackets. And then the attribute's name

01:15.480 --> 01:16.350
goes inside that.

01:16.860 --> 01:19.410
So this is how we would use the "noreturn" attribute.

01:20.910 --> 01:25.650
If we are using an attribute in a declaration, it goes before the thing that it applies to.

01:26.370 --> 01:29.670
Here we have a server() function, which is going to be no return.

01:30.120 --> 01:37.620
So we put the noreturn attribute first, and then the server function prototype. You can use namespaces

01:37.620 --> 01:38.400
with attributes.

01:38.820 --> 01:45.330
So if you're working on the GNU compiler, you can put your directives in their namespace. So they will not

01:45.330 --> 01:47.160
conflict with any other attributes.

01:48.030 --> 01:50.730
And you can also provide arguments for attributes.

01:52.780 --> 01:55.900
C++11 define the noreturn attribute.

01:56.410 --> 01:59.140
This indicates that a function does not return.

02:00.640 --> 02:05.620
Usually if you write a function which does not have a return statement, it means you made a mistake.

02:06.220 --> 02:10.600
Often, compilers will give you a warning for that, so you can go back and fix it.

02:10.990 --> 02:12.100
And that is usually helpful.

02:12.670 --> 02:15.640
But sometimes, you do not actually want to return from the function.

02:16.420 --> 02:23.080
For example, if we have a web server which just has a loop which keeps processing connections until

02:23.080 --> 02:26.980
the program is terminated, then that function is never going to return.

02:27.640 --> 02:28.900
So you do not really want the warning.

02:29.770 --> 02:32.440
So you can say that this function is "noreturn".

02:32.440 --> 02:33.880
It has the noreturn attributes.

02:34.450 --> 02:40.270
That will also tell anyone reading the declaration that this function does not return, and it may help the

02:40.270 --> 02:41.710
compiler generate better code.

02:43.720 --> 02:47.620
C++11 also has the alignas keyword, which we looked at earlier.

02:47.980 --> 02:54.340
This is not actually an attribute, but it is meant to replace the hash pragme pack. But it only works if the

02:54.340 --> 02:56.080
argument is greater than the word size.

02:59.290 --> 03:01.690
So here is our never ending function.

03:02.260 --> 03:07.570
We use the no return attribute. And then we call the function, in the main() routine.

03:10.570 --> 03:11.590
And there it goes.

03:11.890 --> 03:12.670
There is no warning.

03:14.590 --> 03:17.830
C++14 added the "deprecated" attribute.

03:18.730 --> 03:23.230
Deprecated basically means "This code is going to go away soon, so stop using it!"

03:24.730 --> 03:28.930
You could, for example, have a function where you have written a new version with a different interface.

03:29.650 --> 03:32.980
You have not got around yet to changing all the code which calls this.

03:33.520 --> 03:35.410
So you still need to have the old version.

03:35.920 --> 03:40.720
But you want to discourage people who are writing new code from calling the old version.

03:40.720 --> 03:42.190
You want them to use the new version.

03:42.850 --> 03:46.210
So you could put the deprecated attribute in front of it.

03:46.750 --> 03:52.150
And then anyone who calls this function will get a compiler warning, saying that this has been deprecated.

03:52.630 --> 03:57.610
Which basically means you should try and use the new version. You can provide an argument, which will

03:57.610 --> 04:02.290
be an explanation string, and the compiler will include that in its warning message.

04:04.830 --> 04:06.840
So here is our deprecated function.

04:06.840 --> 04:11.130
We have the "deprecated" attribute, with the explanation string.

04:11.700 --> 04:15.030
So, "Please use the new version!" And then we call this.

04:17.950 --> 04:19.600
And in fact, we get an error.

04:19.870 --> 04:20.890
I am not sure that is correct.

04:21.460 --> 04:26.050
The error message is just the text of the explanation string.

04:28.330 --> 04:32.680
If we try this with g++, then we do get a warning.

04:33.130 --> 04:37.600
It says that this function is deprecated. And then it gives the explanation.

04:37.990 --> 04:39.490
So I think that is much clearer.

04:42.860 --> 04:46.600
We have already mentioned the "fallthrough" attribute in C++17.

04:47.120 --> 04:52.460
So this says that we intended to fall through from this case to this case.

04:53.090 --> 04:53.960
It is not a mistake.

04:56.290 --> 04:59.500
C++17 also has a "nodiscard" attribute.

05:00.250 --> 05:06.520
So if you have this in front of a function, anyone who calls this function, and does not check the return

05:06.520 --> 05:08.770
value, will get a compiler warning.

05:09.520 --> 05:14.410
So sometimes, it does not really matter what a function returns. The printf() function,

05:14.410 --> 05:18.430
for example. If you got a warning for not checking that, that would get really annoying!

05:19.090 --> 05:22.150
But sometimes it does return something important, like an error code.

05:22.630 --> 05:25.570
So you want to encourage people to look at the return value.

05:28.300 --> 05:31.060
So here is our function, which returns something very important.

05:31.150 --> 05:33.190
It has the nodiscard attribute.

05:34.450 --> 05:37.660
And then we are going to call this function, and ignore the returned value.

05:41.310 --> 05:42.060
So there we are.

05:42.090 --> 05:47.200
We get the compiler warning. "Discarding return value of function with nodiscard attribute".

05:48.840 --> 05:50.970
Attributes do not just apply to functions.

05:50.970 --> 05:56.610
They can also be used with variables, types, members of structs, classes, enumerations, and so on.

05:57.510 --> 06:00.720
With a type name, the attribute goes before the name of the type.

06:01.230 --> 06:07.140
So if we have a struct Test, which is nodiscard, then we put "struct", then the attribute, then

06:07.140 --> 06:08.340
the name of the struct.

06:09.450 --> 06:14.490
So this will mean that any function which returns a Test object will be nodiscard.

06:16.170 --> 06:19.770
So there is our struct Test, which is nodiscard.

06:20.280 --> 06:22.260
This function returns a Test object.

06:22.860 --> 06:25.740
So this function is, itself, nodiscard.

06:26.370 --> 06:31.350
So if we call this without checking the return value, we should get the same warning again.

06:32.950 --> 06:33.520
And we do.

06:34.240 --> 06:37.510
And the last attribute we are going to look at is the "maybe_unused".

06:38.470 --> 06:40.420
So if I just quickly remove

06:40.420 --> 06:41.560
that, for a minute.

06:43.780 --> 06:49.600
So we have a local variable here, which is not used and we get a warning for that: "unreferenced local variable".

06:51.580 --> 06:55.570
And if I put this back, then the warning goes away.

06:56.290 --> 07:00.580
So this could be useful if you have a function where you declare all the variables, but you want to

07:00.580 --> 07:02.860
test the function before you have finished it.

07:03.310 --> 07:05.980
So you may have some variables which are temporarily unused.

07:06.580 --> 07:08.380
So this will get rid of annoying warnings.

07:09.250 --> 07:10.630
Okay, so that is it for this video.

07:10.990 --> 07:11.800
I will see you next time.

07:11.800 --> 07:13.840
But until then, keep coding!
