 Hello and welcome to the NPTEL course on an Introduction to Programming through C++. I am Abhiram Ranade and the topic for today is some advanced features of functions and the reading for this is from chapter 12 of the text. So here is an outline for this lecture sequence. I am first going to talk about passing functions as arguments to other functions and this will be in two ways functions, function parameters, there will be two subtopics sort of and I will also talk about lambda something called lambda expressions. Then I will talk about how to assign default values to parameters of a function and I will also talk about something called function overloading. So let me start off with the function bisection that we wrote some time ago to find the square root of 2. Let me begin with the function bisection to find square root of 2. So here is the function. So this function is meant to find the root of any function and we are going to use it to find the square root of 2 by finding the root of a function x squared minus 2. So x squared minus 2 would be 0 at square root 2, so if we found a root of this function x squared minus 2, we would have found square root of 2. So this function does do that and we could use this to find other things also. So say you want to find the cube root of 3, what should we do? Do we need to write everything again? Well not really, we should only write things which have to be different as compared to finding the square root of 2 and there really are only 2 places. So this is the place where we were evaluating the polynomial x squared minus 2 and here is a place where again we were evaluating the polynomial. So only in these 2 places the actual polynomial that we are evaluating is important and for this we would need to evaluate the polynomial x cube minus 3. So over here this should be x cube minus 3, xm cube minus 3 and this should be xm cube xl cube minus 3 again. So that is really the change that we want to make. So we could change the text but is there a better way of doing it? So the general question is can we write a bisection function which finds the root of any mathematical function whatsoever provided it satisfies the requirements of bisection and those requirements were that we need to supply to bisection 2 values xl and xr such that the signs of the function whose root we want to find are not identical at xl and xr. So that is what bisection depended on and we should satisfy that but we would like it like a single function to be used to find the root of any mathematical function. So a natural idea for doing this is well to bisection we should pass somehow pass the mathematical function whose root we want to find. So there is an extra argument and that argument should specify the mathematical function whose root we want to find. Now how do we represent a mathematical function? How do we tell bisection that look here is the function? Well a natural idea again is that after all we have C++ functions which compute the function which whose root we want to find. So suppose we could somehow send that C++ function that should somehow be adequate. So in the case of our square root of 2 we were trying to find the root of this function f of x equals x squared minus 2 or the new thing that we want to do use bisection to find the cube root of 3 we want to find the root of this function. So somehow we should supply these functions f and g to the bisection function through that extra argument and maybe that should somehow be able to make it work. So now the question is that we have a C++ function bisection and to it we want to pass another C++ function so f or g whichever one we might be interested in. So how do we do that? So in short this is what we would like to write as far as the rest of the code goes. So here we have defined our f we have defined our g and in the main program we have an extra argument. So this time we have given the argument f presumably they should somehow send this function over to bisection to the function bisection and bisection should print the root of root corresponding to this that is it should print the root of square root of 2. And similarly in this case bisection should be sent this function this g over here and again after it executes bisection should print the cube root of 3. Now exactly how do we pass a function h to another function v well let us say let us see suppose h has this declaration. So return type h and the parameter list. Then in the parameter list of b to which we want to pass s we need to put in the type of h. Now it turns out the type of h of a function defined in this manner is something like this. So it is this funny looking quantity or funny looking string so it begins with this word function and then angle braces return type all of these things. Now this is for a general h but the function we want to pass to bisection takes a single double argument and returns a double all such functions that we want to pass are going to take a single double argument and return a double. So we can say that the type of all such functions is function return type double and single parameter type also double. So we have discovered how we can declare what should be in the parameter list of bisection. So we need to put this in the parameter list of bisection. So bisection is going to have this declaration. So these were the original parameters and this now is the new parameter. So this way we can that extra argument that we sent for g will be received by bisection as this argument h and in fact inside bisection we can write calls to h. So bisection can just directly use, we do not need to modify the function. Modify a function to include the code for h explicitly. Of course we need to modify the function because we have added that parameter. So here I am showing you the new version of bisection. So what has happened over here is that the red portions are where some changes happen. So first of all we need to have, we need to include a new header file. So this header file is called functional. So this file contains code which allows you to write something like this. So function is a name which is defined in the standard name space. So if you want to use all these things you must include this header file functional. So we have the bisection function and we have an extra parameter now. And then if you remember here we were calculating that function whose root we wanted to find and now we want to find the root of h. So we are going to calculate that h of xl and here also we were calculating that function at xm. And again since we now want to find the root of h we are just going to find h of xm. What this is going to do is this is going to call h, h is after all a function which is present in the memory of the computer. So it will call h with argument xm and xl here and get that value and use that value. That is it. So now we can use this together with this same main program that we had written. This together with the bisection function that we just showed will allow us to do what we found desirable over here. So this will indeed print the square root of 2 and the cube root of 3. So let us do a quick demo of this. So many roots is this program. So at the top I have written down the bisection as we had in the slides. Then we have f and g also as in the slides and then over here we have our main program. So main program is doing just what we said. So ideally if this runs correctly we should expect square root of 2 to be printed and cube root of 3 to be printed. So let us run it. So let us first compile it and then run it. So indeed it prints out 1.41418 which is a good approximation to square root 2 and 1.4422 which is a good approximation to cube root 3. So here is a exercise for you. Now what is given over here is a function which does take as an argument a function f which takes two integer arguments and returns an integer. And it is somehow using this inside and it is going to return this result value. What you are supposed to do is write a main program which calls this twice with appropriate functions passed for f so that the first time around it should return the sum of the numbers between 1 and n. The first call should return the sum of the numbers and then the second call should return the product of the numbers 1 through n. So this should be n factorial. And here is a little bit more detailed exercise where you are supposed to take a function and a range of x values and y values. So you should plot the values of the function which start at x0 and go to x1 and which lie in the range y0 and y1. And to look nice you should do things like maybe plot that rectangle, show that rectangle, maybe leave some margin. So just try to make it nice. But here is a really good use of why you might, another good use of why you might want to pass a function. If you want to find, if you want to show the plot of a function then you might want to write a single function which does the plotting and to which you can just pass functions, whatever functions we want. So what have we discussed? So we said that we often want to write functions that operate on functions. So say for example functions which find roots of other functions or plot functions. Such functions can be written conveniently because C++ provides a mechanism to pass a function to another function. And for this you need to include the header file functional which tells you, so which allows you to define the type of the functions that you are passing. This concludes this segment. In the next segment I am going to talk about lambda expressions which are, which is one more way of doing all this and a little bit more convenient way at that. So we will take a short break.