Templates in C++

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hey what's up guys my name is Jonah and welcome back to my safe loss loss series so today we're going to be talking all about templates and I know that you guys have been requesting this for a while but it is kind of an advanced topic so I didn't want to jump into it too quickly but today we're finally going to start off with a fairly gentle introduction to templates in C++ so first of all what is a template well those of you familiar with other languages might see this as kind of generics Riesling Java or C sharp they're kind of called generic templates are completely different well they're not completely different but they are like infinitely more powerful than generics in those managed languages right templates are almost like a bit of a macro they let you do pretty much anything whereas generics is very heavily limited by the type system and by a lot of other factors templates specifically are much more powerful and we're gonna see this as we go along don't worry I'm gonna probably end up having like dozens of videos on templates or something like that so by no means is this gonna be the only video I make on templates templates are such a huge and complex topic and can be incredibly crazy so we're gonna be exploring all of that as a serious goes on so first of all well what is a template a template basically allows you to define a template that will be compiled but like by your usage if that makes sense you can get the compiler to write code for you based on a set of rules that's really what a template is just the compiler writing code for you based on the rules that you've given it when I write a function for example and I use a template in that function what I'm actually doing is creating almost like a blueprint so that what I decide to call that function I can specify certain parameters which determine what code actually gets put into the template and that is all kind of determined by the way that I actually use that function again it's a little bit difficult to explain and in fact I could just give you the definition that's on like say BP reference or on Wikipedia I'm trying not to do that obviously I think the best way is just gonna be to show you what it actually looks like in the code so a good example of why I might want to use a template is if I want to create a function that is largely going to be the same but may take in different types maybe I have a print that I want to use to print integers so I might do something like print in value and all this is gonna do is see out my value and if I go back down to main I can call print with a value such as five and everything will be fine now what if I want to actually use a string there instead like Hello so suddenly I need to actually define another overload for this function which actually takes in a string so just like this note that I'm actually passing this string by value here because I want to kind of have it be the same as my print function here which also takes in the integer by value then I'm going to basically end up copying and pasting this code this works fine in order for this to actually compile though we do need to include string now what if I want to print a float well you kind of are seeing the picture here I hope if I want to print a float like five point five then I also need to basically copy and paste this function again so now I have three different functions here which basically the only thing that changes here is the actual type of data I'm passing in because C out can of course accept any kind of primitive or or built-in C++ type that we're actually using here so what we've ended up with is manually defining three different overloads for a print function that's okay some people actually prefer to do it this way but what if we could just define that function once a good goal for software engineering in general really is to kind of avoid code duplication right because if we decide to actually change one of these print functions to do something extraordinary we decide to go from using C out to print air for one of our own custom logging functions we have to change it in all of the places that we've actually defined that right so in this case in all three print functions we have to actually just occurred what if we could just write that code once and then somehow be able to fill in the blank for the type that's where we can use a template so instead of writing this code this many times what I'm actually going to do is just convert this into being a template the way that we do this in tactically is before the return type we write template then open an angular bracket type name and then give it a name typically T is used and then finally we can use T instead of our actual type over here so this becomes void print T value suddenly if I actually compile this code by hitting ctrl f7 you can see it compiles just fine and if in fact if I run my try by hitting f5 look at that all three all three functions actually work even though we've just written one function so how on earth does this work and what's actually happening here well the first thing that gives away that this is an actual template is well the word template right this means that this is a template that will be evaluated at compile time so basically this is an actual code this isn't actually a real function this only gets created when we actually call it and when we call it based on how we call it with what types does this actually get created and compiled as source code now this next part is something called a template parameter in this case we've chosen to use type name as the type of template parameter and then T is just a name so this could be anything we could call this type with the call this churn over the course anything we really wanted to and so what happens is this specific variable name this template kind of argument name we can use that throughout our actual template code to substitute whatever type in this case gets used so what we've done is instead of just writing int value like that where we've written T value which means that when we actually call this code whatever type we specify here is the type that actually goes into this argument now this is a little bit harder to read in this case because when I actually specifying the type explicitly it's just kind of getting it implicitly from the actual parameters here in this case but what we can do is when we call print we can actually specify using angular brackets here the type that we want so for example print int if I let's just get rid of these and keep it real simple for now so what we've done here is we've pulled the print function with the type int this this template argument here accepts a type name now you can also write this as class by the way it is exactly the same synonymous right class class type name I tend to use type name because class by just reading the code class kind of implies that it has to be a class type that's not true as you can see this coastal compiles even though I'm using int so because of that I tend to just use type name because it just makes more so we write type name T which means that the first half of that argument that we have here is an actual type so we can write end here we can write STD string we can write whatever we want obviously if we write STD string then what actually happens as T gets replaced with the type that we've specified STD string which means that we are obviously are taking in a string value hence why this code is not compiling so we actually have to write something here like China or something now if we go back to our five example we can specify int here but we don't have to if it's possible for the type to actually be worked out by the argument that we use here either by the return value which which we can talk about later or by the actual parameter here so in other words a plus boss knows that five is an integer it can automatically deduce what type T should be which is why we don't actually have to specify it using those angular brackets which makes our job a bit even easier now that being said let me show you explicitly what actually happens if you do not write anything so I'm not using this print function at all this print function does not really exist this print function is just a template which actually gets created when we call the print function with the given template argument and I can even prove this by making a syntax error here so let's just say instead of value I forget not a know the e or something so I'm just printing value now clearly this is an error because there is no variable called value so if I hit control f7 to compile my code look at that it compiles just fine and that's because the template doesn't really exist until we call it if I go back to my code and I actually try and call print with like the value 5 or something and hit control f7 at that point you can see I actually do get an error here telling me the value is an undeclared identifier and again that's because the template only gets created when we actually call it because it's just a template it's not actual card it gets materialized I guess into real code that gets sent to the compiler and compiled based on the usage of the template now MSV c won't tell you about errors in templates that you're not actually using some compilers like clang actually will so it is kind of compiled dependent but in this case you can see we don't actually get any errors we've written code that's not really correct but until we call the template it doesn't exist so we don't get any compiler errors so what actually happens when we compile this template is it knows in this case that we have used five here right which means that the type name is actually an integer so what happens is it basically fills in the blanks here so it would be equivalent as to if we just copied and pasted this method and then replace T with an actual int because that's what we're calling here and now this is a real function that has to get linked and everything when we actually compile and Link this code so let's just fix that syntax error we had there and that is actually what happens in this case now when we call print with a different argument like a flirt for example another version of this template actually gets created so this gets copied and pasted and then instead of T this time we're using a flirt so you kind of get the picture really all this is is a template specifying how to create methods and these methods all these functions can be created or automatically by the compiler based on your usage of them which is pretty cool now templates are by no means just limited to types or anything like that and they're not limited to functions either you can actually create entire classes based on templates and in fact that's a lot of what the standard template library actually is in C++ it's just completely using templates let's take a look at an example where we're not actually using a type as a template argument and let's do it for a class instead of for a function let's just get rid of this print function that we've created over here and let's create a class suppose that I wanted to create an array but I wanted this array class to actually be created on the stack so what I basically mean is let's just create a class called array and then over here maybe it's an integer array in this case I actually want to have an array that has some kind of size that is determined at compile time now I can't just kind of put in a variable size or anything like that because since this is a stack allocated array it actually has to be known at compile time now obviously we could use alakay or something like that to grow the stack dynamically we're not going to use any of that in this example we just want to basically create a normal kind of see style array on the stack so this size value does in fact have to be known at compile time now templates are evaluated at compile time so this is perfect what I can do is convert this class into being a template but instead of using type name as it as my template argument I can actually use just an integer right I'll call this n which is basically just as for number and then instead of size over here I'm going to write n and then finally I'll just add one public function to this array which is just going to return the size of the array so I'll write int get size and then I'll just return and okay so what's going to happen here is exactly the same thing that actually happened with our function when we call this array and we specify a size like five and I'll just call this array what happens is if this card gets compiled based on its usage so in this case five is the template argument which means that a version of this class gets created which replaces n with five like that and like that so this is actually what we end up with this is the code that we end up with and then of course if I call a raid or get size here and print that to the console or get rid of this extra copy I've created here that's my card let's hit f5 you can see that I get five printing so that's how it works so you can see that we don't just have to use types we can even use integers or other data types to basically specify how we want to generate a class an entire class in this case let's go one step further suppose it is said of this being an INT explicitly oh I also wanted to make the type actually variable so I wanted to be able to specify what type this array actually contains at compile time well I can add another template arguments let's add this one before the number so I'll just write type name T and then int n right so now I'm going to replace this int with T and suddenly what I've got is an array of type T which is specified at compile time by the template that is of size n which is also specified by compile times so now over here what I actually call this array I have to specify int as an example and five for my size and I can obviously change this to be anything I want like SAEs string and 50 or whatever and you can see that what I've created is kind of a class that gets automatically created every time I actually use this array so that's pretty cool and what we've actually created is very similar to how the standard array class actually works in the standard template library that say the say plus plus right it just has two template arguments type and size and it creates an array very similar to the way that we've actually done it here now this is a sort of matter programming in C++ because you can see instead of actually programming what our code does at runtime were kind of programming what the compiler will actually do during compile time and this is extremely powerful now what we're doing here I think this is a pretty good kind of gentle introduction we've even kind of gone as far as to create multiple template arguments and use integers instead of just kind of type names but this is just scratching the surface I mean this can get really crazy really quickly and because of that I kind of want to talk about where you might want to use templates and where you might not want to use templates so this part is kind of entirely subjective it's opinionated but in my experience this is this is how it works right so first of all a whole bunch of game studios out there or software companies whatever actually just outright down templates they say never use templates ever now I think that's a little bit kind of overreacting to the situation because I think the templates can be extremely useful for situations where like I don't know like a logging system or something like that you have every possible type that you want to log do you really have to like specify an overload for every single function well you can automate that with templates right you can get the compiler to write code for you based on a set of rules that's really what a template is just the compiler writing code for you based on the rules that you've given it and based on the usage of that function or class or anything like that right that being said if you start using templates if you start getting really really complex with your templates and you start just having it generate an entire like meta language for you and I've seen code that would probably give you nightmares like seriously you can go really far with templates that might be pushing it right that might be going a little bit too far because there's a point where the templates become so complex that if there's an issue with it no one can understand what's going and you'll literally have to just get like a notebook get a piece of paper and start filling in all these types manually of course you can get the compiler to actually tell you what code is generating and all of that but even so like at work we've had cases where we've just had to sit down and spend three hours figuring out what code has actually been compiled and what's going on with our templates and why they're not working when that happens I think you've gone too far and I don't think that you should get too crazy with templates even though you can there is a point where doing things manually and writing out code yourself is actually going to benefit you and your team a lot more than trying to create this massive template magic that just does everything for you but is kind of fragile and very difficult to understand so I don't think the template should be completely banned but I also don't think that you should go crazy templates and abuse them a lot anyway we're gonna have a lot more videos about templates because there's a lot more than I want to talk about is just scratching the surface once we actually get into kind of the game engine series as well will people start to see real examples of where we might want to use templates off the top of my head I think two kind of really important places where I would definitely use templates are things like logging systems and also even like a material system like for rendering graphics right when you have a uniform buffer that can contain various different types templating that to an extent can be extremely useful anyway I hope you guys enjoy this video if you did you can hit that like button you can also you can you can help support this series in all the series that I make here on my channel by going to pay for a Mac on 4/2 Cherno massive shout out as always to all the wonderful supporters that helped make this possible there are some pretty cool rewards that you can get such as access to all the source code from my OpenGL series as well as the soon to come game engine series by supporting then you also get like for the top tier supporters we do this thing while we basically hang out for an hour once a month and we just talk about whatever the next one is actually coming up in like a week so definitely sign up for that if you're interested and then also you'll get videos early and a whole bunch of other rewards but most of all you're helping to support this series which is awesome because I can basically just lets me make more videos you can also join discord I have just called server over - sherrilyn home slash discord that's basically just a community of people where you can talk about whatever you want including this programming stuff and just discuss it with other people ask for help with your kirtan all that definitely encourage you guys to join that and as always I will see you in the next video goodbye [Music]
Info
Channel: The Cherno
Views: 349,325
Rating: undefined out of 5
Keywords: thecherno, thechernoproject, cherno, c++, programming, gamedev, game development, learn c++, c++ tutorial, template, c++ template, templates in c++
Id: I-hZkUa9mIs
Channel Id: undefined
Length: 17min 58sec (1078 seconds)
Published: Wed Nov 08 2017
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.