CPP-03 Modern C++: Google Test, Namespaces, Classes (2018, Igor)

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
okay thing it's time to start again right so welcome back it's going to be another lecture and we're gonna start off from where we stopped yesterday I guess so yesterday we had to kind of rush through the whole seeming experience because there was not really enough time because we spend some more time on like debugging and showing the internals that I expected so today we are going to talk about using unit testing for your for your yeah sure the audio on this recording will not be the best right so today we're going to be talking about how to use unit testing for your codes what are namespaces which we already have seen but now we will understand how to use them and what they are and we will start the introduction to classes which will be a huge part of this course really and before we start off I think I will go through the whole see make thing again but I will not show you slides we will try to code something right so to give you a perception of what how hard is it to set up a new project in C make for instance right so what we what I have here is I have a temporary folder and I just created a Simek project folder and you can see that it's empty there is nothing there yet so what we will do is we will we will create a we will create an empty cmakelists dot txt we will create a folder source and for now that's I think that's all that we need here so for now we have a Simek lists and source so let's go ahead and try to modify the C make lists okay that is not what I want just a sec let me just make it more usable come on okay right so let's modify the Simek list and as I told you there are two commands that you must call its project and let's call it C make test project and we need to to specify the minimum version that we ask from our system to have and of see Mike and we're going to be working with version 3.0 so there is it's not very important which version we pick just don't pick so anything that starts with 3 is fine now I think C make is in version 4.5 or something but three-point always is a good start the timing okay so this is kind of the bare-bones project that that we can set up and to build this project I think we can already build it at this point even though it doesn't make any sense but building you can do it from the same folder but then you have a lot of files populating your project which which is a pain to clean up so never do it not in a build folder so you always want to create a built folder and it's an empty folder so there is nothing there and what you want to do is you want to do C make dot dot so C make takes a folder as an input it takes a folder with that contains a cmakelists dot txt right so our folder that contains seam xt is one folder up from us is our parent folder so that's what we do so we run CMake and it does a bunch of a bunch of things and at this point it's not very important what exactly does but you can if you look at it you will see that it it detects like the cecum pile already takes the C++ compiler and it checks if your C++ actually works and so on so what it does is it populates this folder with a bunch of files over there so a very yeah so basically the main the main file the most important file over here is this make file so the make file is actually it's a sequence of commands that will actually be carried out that will it's a sequence of commands path to compiler so this thing actually calls the compiler and you can look up what this file looks like it's usually kind of scary because see make generates a big one let's see if we find anything useful in here not really because we don't have any code yet so there is nothing that is useful here for now there will be and the important part that you need to remember is you never need to modify this mic file this mic file is only there to help you build the code and see make takes all the responsibility for it so Simek generates it and to run this mic file you just need to run make and in this situation doesn't do anything because we don't have any anything to build we didn't add any files to our projects it's a dummy project for now so let's let's add some files again like if at any point something of what I'm doing is not clear stop me ask me because you need to understand this very well because you will use that for homework you will need to set up most of the CMake project on your own right so let's modify our C make C make lists we did have a folder source there so that's where all our sources will go and we will populate it at some point but for now let's just try to use that folder even though it's empty so what we want to do is we want to add subdirectory and we can either just say source here so again in C make every everything is string so by default this source over here will be a string it's probably even make it a bit bigger okay so and also all the relative paths will be extended from this cmakelists file so from the folder where this C make lists live lives so in this situation we don't specify any path over here and usually it will be extended from the from the root of our project because that's where our C make lists lies if you want to be really precise if you want to know exactly what is going on you can use variables so you can use project source dear and add a slash to it this way you've just constructed a path like a full path so this this variable over here it's a seeming variable it's a standard variable is going to be populated on every run of Simek and this variable will be will be so you will concatenate this source to this variable over there which will give you the path to your source folder we can also to make sure that everything works we can also output this project source dear and so let's have it so that we can easily see it let's just put some tag over here and copy this thing over all right so at this point let's try to to build it again I wonder now okay so just run CMake and so first of all we see our tag over here and you can see that it has it has been populated to the folder where we actually are so - where am i - temporary CMake project which is the folder where i created the project in but then we also have a an error and this error is very descriptive it's an error with this add subdirectory and the problem is that this subdirectory doesn't have a see make lists at all and it must have whatever you use was at subdirectory there must be a see make lists in it it's a rule of C make basically so let's make C make happy and let's go to source and in the source let's create a C make list.txt so the cool part about C make is you can specify your build key arkla right so you don't need to specify all the build in one huge file you can actually think in modules so think modular design so if I have my source folder and the source source folder has many other folders I can have a small C make list for every of those and Simic will handle that properly but we can also have an example for that if needed so let's just save this empty file there it does nothing it just exists there right and let's try to rebuild our code again okay so now it built it still shows us our message and everything is fine because now it found the see make list but it's an empty simile so it doesn't have to do anything but at least it has found something so if we type make it still does nothing because the make file that it generated does nothing it just sets up the project and that's it okay at this point let's probably add something useful to it right or at least borderline useful let's in the source folder let's add some files like so let's add for now one file say main CVP and it's gonna be our typical nope so it's going to be a main function and yeah let's do something useful so let's do again like the hello world application I think it's fine to do here yeah yeah hello is enough and down alright so now we have some file over here and we can build it on our own we have done it many times so I will skip it here but we now also need to to tell to tell see Meg that there is such a file that it has to build this file and for that we need to modify the see make lists within the source folder so the one that is in the same folder with our file so we go here and there is a very simple command it's called add executable and we just say we want it to be called main or let's let's give it some other name to make sure that that there is no ambiguities and you understand exactly what it goes where and what we want to specify for it is we want to specify that all the files that should come in to that in executable usually it's one CVP file you you generally want your your executable to contain one CPP file with one main function right so whenever you do add executable that is the thing that you will be able to actually execute it will be a binary and it has to have a main function in it okay so at this point we have done something useful with the project so let's try to to do it again so we did the C make it showed us exactly the same things as before but now if we type main if we type make there is something happening over there so you see all this colorful output and the percentage of how far are we in our build and basically what it does it creates all the boilerplate things that we did before like create objects linked objects and so on it does them here and you can just use your bin main so let's see what we have in our built folder now again all the built files will always be in the build folder they will not be scattered around and this is very a pleasant feature because the built folder you can just ignore from your git and nobody should ever see it apart from you so it's your local folder and if you if you are not happy with your build you just remove it and start over again right so now it has a new thing there before there was no source folder over here now there is source folder over here and if we go to this source folder there is our there is some more files that are needed for Simek but there is this binary over here so if we just run it it's gonna print us hello so just to show that it actually works and does what we expect it to right so why does it why is it stored in source folder that's because the actual file is in the source folder so the build the structure of the build folder mimics the structure of your project if you have something in source blah blah it will be in build source blah blah okay good but then why do we need see make at all is not for just creating executables we know how to do that that's really simple right so we want some library let's try to add some library to to the project we need to go back to the source folder and let's create some no not my dear let's do some header file so let's have a hello dot H for instance because that's what it's going to be doing again the name of the file kind of should represent what it is supposed to do okay so if we go to hello dot H we first need to start with pragma ones because we don't want it to be included multiple times again including means copying so if you don't do that and you have multiple includes in your whole project and this file gets included multiple times it means that it will be so you will have the definition of the function exactly the same definition multiple times in a row and that will be an error in your compiler so if you forget that you will get errors while compiling your code okay and let's have some function it's going to be a void function it's going to be print hello and what we want to do is we want to also add iostream here and we want to print the hello function here alright so now we have our extremely useful function and you can see that I now not only declare it in header but I also define it in header right so that's a bit different from what I was talking about and I feel like it's important to understand the differences now what can I do about it let's go to the main function and let's remove our C out we can now include the other file and we can include it with just typing hello dot H this is something that that Google tests will will actually not be happy about because it will tell you that you need to that you need to include the directory when named in dot H file and I hope ok that is seen good and we will come to that later if you just wanted to shut up you can do something like this this is this means that you are looking for something within this folder but you are explicitly specifying a folder for it this way you don't have a warning but it's not a very proper way of doing it we will come to that probably later ok so at this point we use our hello so now we can actually use the function so let's try to use our function and we use the print hello function over here so do we need to change anything in our in our build like who has some understanding of what is going on like who who thinks we need to change anything in our build to build it ok do you have a guess of what what I mean update [Music] yeah we did okay yeah so anyway like you don't need to modify your build at this point at all because header files are just copied right so you basically just have if you just include it you don't need to link anything you don't have to do anything that's called so what we now have implemented is a well known word of a header only library so it's a library that consists only of headers everything is implemented in headers and you never need to link it that's the good part of it but it needs to be compiled every time it's included so every time you include it it's not for free you need to pay with your compilation time for it so in this situation we can go to our build folder again and we can rerun see make run make and let's do our source be in main and now we get an output hello function instead of hello right so it uses our function we didn't need to do anything we didn't need to modify the bill Simek doesn't have to know about header files apart from where to search for them and there is a difference between using the the brackets kind of the the angular brackets like this and the the quotes for for includes the difference is is that if you use the quotes the compiler will think it's a local file so it should be searchable from within this file over here the one that we are in right so in this situation we have a so in d and actually let's even do it here no okay maybe I can I just want to show you the structure of the project and yes of the main okay that was not a good idea because we have a build let's remove the build okay so our structure of the project looks like this now so we are here and there is a source folder there is a hello there is a main.cpp and you can see that hello is in the same folder as main.cpp so that's why we can we're able to find it with the with the quotes I believe that if we if we put not the quotes but these symbols over here we should get an error I hope otherwise I'm wrong let see make yeah okay so you can see that now it cannot find the hello dot H file that is because if you use the angular brackets it does not search for this file within the same folder where you are so it's not it doesn't consider it to be a local pass but it considers to search it in all the system paths that it has and these are a lot we will not go deep into that now but there are many system paths and what you can do in what you usually do you don't usually search for for headers in your local folder but you usually specify in the C make a folder where all your headers should be found so let's try to do that let's help C make finding this file for that we need to modify the topmost C make the one that has our status message and for that we need a command that is called include directories so include directories tells see make to specify whatever folders it can be many folders here it doesn't have to be one it can be as many as you want and the list just looks kind of like this so if you if you want more of them you just add more of them it's very easy so what what it's what it tells us is that all our headers should be searched for starting from that folder over there in addition to all the other system folders that are already there so what it tells it now is that we expect that our headers should be in the in this in the source folder so now that we added this let's try to rebuild our project and now it's suddenly builds because now see make can find those files ok are we on the same page so everybody understands the difference between the angular brackets and the and the quotes right ok good right so for now we have done a header file but we didn't really do a library we still could have just done the same thing with our common c++ way of just compiling it all in the command line it would still all work we don't need any link in there where see Mike shines is where you have a lot of things that should be linked together so let's try to do that let us modify our so let's create a new file let's go to source and let's create a new file hello dot CPP and we will just copy this function over there and this file needs to so every CPP file that is part of a library should include the file with the headers of this library so every library has headers which is the definition and the implementation which is the CVP so they should be separated and they usually have the same file name with the only difference of one is being dot H the other is dot CPP okay so what we need to do is we need to include here hello and we know that hello is in the same folder so we can just use the the quotes over here and what it now says is like I mean I could compile it but it does the same thing for me it just shows that there is a redefinition of print hello and why is that because there is a definition in the header file right so in the header file we already had the definition of this thing and we just need to remove that definition now it has to just be a declaration so why do people do that what's the use of it like why to complicate our lives separating things into multiple files that's because it's much easier when you read the code so when I read the code I generally don't care about the implementation again if the function is named in a proper way and everything is and I trust the developer to some degree I mean you never trust somebody really but they can convince you that they are trusted by providing say a complete set of unit tests for their code and if I see that their library passes hundred unit tests and the name suggests that this function does it I have no reasons to believe that it doesn't do it so this way I never ever need to see this the implementation of the code even if I can what I need to see is I need to see the interface of the code the interface by which I can call some code and this interface is then encapsulated in a header file and it's very simple to read you just open it you see all the functions all the definitions of the declarations of the functions and that is the only thing that you care about so it's not it does not contain any information that you don't care about you don't have to scroll through it you just look at the function you look at its signature you look okay I can use this function like that so that's why people do it like one of the reasons good so now we did that and let's try to so if we just try to build this thing now we're gonna get an error we're gonna get an error because there is an undefined reference over here undefined reference to print hello that's because now we only include the file but see make and our build progress doesn't know anything about this the hello dot cpp we have never told it there that there exists hello dot cpp so the only thing it does is it just includes the header file which just contains the declaration of a function and we're missing a definition whenever we're missing a definition we will get the undefined reference error all right so let's try to provide some help again to see make with it for that we need to modify our C make that is in the source folder so we have an executable over there and what we need to do is is add library so we want add library and we want our library to be called hello and the hello library is defined in the hello dot cpp right so again in c make you generally don't ever ever care about headers headers come for free you can just use them and that's fine so you never need to define them what you care about is the actual CVP files so what this thing will do it will find the hello dot CPP it will consider it like okay well there is a CPP file and I need to compile it so it will compile this file into object files and will pack them into a library for you you never need to do anything about it you will just get a library and by default you will yeah [Music] okay so let's try to open them side-by-side oops I mean I meant this come on all right so on the left is the header file on the right is a CBP file for the library just the Declaration of this function yes so this thing is called a Declaration of a function like it can be confusing I always confuse this two words the Declaration and definition they are they sound very similar but basically declaration means you declare that something exists somewhere you just say well trust me it exists somewhere that's what the header file is for so the header file just generally tells you like here use it like this and trust me it exists somewhere the CPP file says yeah I'm the one who you trust like I'm the one who implements the thing and that's what you how you think about them so every library has a bunch of header files and has a bunch of CBP files and every header files tells that this is the interface to my library use it like this the CBP files file is actually doing the work for you okay good where did we stop now so okay right so we edit we edit a library but the issue for now is that we now have a library which is one binary object and we have an executable which is another binary object but they do not know about existence of each other and that is a problem because from perspective of our bin main it still has it still has no idea where to search for the CPP file or for any object of for any compiled code that it can actually run because it just sees the header we still did not communicate the existence of the library to the executable and that is what we do with the target link libraries and we need to specify what we linked and then know like yeah ok so the terminology here is kind of weird so we let me just first type it and then maybe it's it's clear so the first parameter is the binary that we want to link something to and the second parameter is the thing that we are linking to it so in this case we say that our bin main should be I'm not sure about the terminology but anyway consider them that they are now linked okay so now bin main or whoever is on the first position of that of that function knows about the existence of a library called hello okay good so at this point this thing should work and it compiles properly so there are no issues in that and you can even see that it these lines show you what it is what is being compiled so it's can in some dependencies of target hello so there is a target like everything that it compiles it calls a target that's how see make likes to call things and hello is our library and you can see that it's linking as see exact static library Lib hello dot a so it has created a library it's by default it is a static library and it created a Lib hello dot eight dot a over there then it does the same thing for our binary so in the binary it does linking executable bin main and it links the executable and it also links it to to our library and at this point we can just let it run and we still get our hello functions so that thing works as expected that is basically a very bare-bones project in in C make done from scratch right so that's the minimum code that you need to make something run but the cool part about it is now if you have multiple libraries you can you can use them all in the in the same bin Maine so let's try to do that maybe so let's go to source and let's do a Sabol what do we want any good idea for the function I love this yeah blah so let's do a blonde let's do blah CVP so blooded age will be we need pragma once we need voice print bla include a stream wait I didn't so it should be just the the Declaration and in the blood dot CPP we need to include our blood at H and then actually create our function over there all right so now we have two of them and what we can do is we just need to we just need to modify the C make lists in the source folder and let's now add another library and let's call it of course blah and now what we can do here is we can actually link both of them to our to our binary so at this point if we now also change our main function to also it also has to include the blah thing and let's also print blah good so let's try to build this one and this thing works as expected let's also run it and it shows us the hello function and blah okay so that's like now we can add as many libraries as we want we can link them to as many binaries as we want and so on so that's why people use Simek because now it became very simple and very very readable so the good part is that this is much more readable than creating multiple object files then create putting them into a library and so on you can also specify which library will be created so by default it's static and it's as if I would type static here but I can also write dynamic over here and let's try to rebuild the code again yeah there was an error why was there an error did I share it sorry not not dynamic sorry for that it should be shared alright so the the only difference like everything still works as expected the only difference is now we have dot as all in the end so dot a is a static library dot s o is a dynamic library and again the way to think about that is a static library when you link it into your binary it just gets kind of physically copied into your binary so whenever you move your binary around the library will be inside of this binary ok so your binder who will get bigger but it will have everything with it so it kind of brings it home with it you know like like a like a turtle or something but if you have a as a library it's it's stored somewhere else it's stored somewhere on your file system and the only thing that is added to your binary is a way to search for it so when you run your binary the first thing the binary will do it will try to search for all the libraries that it that it needs to and it has some predefined ways for that we will not go deep into that but it searches for one and that's it so that's all you need to remember about those so if you want to distribute your library you generally want to distribute it as a as a shared library that is probably why it's called shared two and if you want to keep your library and you want your code to run fast as a rule of thumb you generally have a static library good so do you have any questions to that because now we can still try things out on a simple example if not we're just going further and deeper into that ok who completely understands what is going on okay whoever doesn't what are your issues what is not clear yeah so yes so I have a like my feeling about this is I totally understand what you're talking about and the issue with simplicity of things is when they break so whenever like I've also started my life as a civil sauce so I used an IDE to do stuff and I was just clicking one button that should magically do something but then when something didn't work I had no idea what to do I was just randomly clicking stuff and like putting like this is like if I change this settings and I google for something elegant change something like if I put this here does it change anything and so on like it's it's a painful process and the problem like the underlying problem of this whole thing is that you don't understand what you're doing and I feel like you know you can use different languages like so I have issues with using Java or Python as a safe first language because they make things simple but when something breaks you instantly have to learn everything about it and they are complex like the the underlying things behind that are really complex this is kind of a middle ground so yes it is a bit more complex when you start with it and there is I mean it's not too many files it's like you have a project structure it's you have basically now to see make they're completely hierarchical so if you think about that is a keyer ARCIC on model it becomes simpler and everything that you need to actually compile stuff is within one see make list within one file right at this point and what is good about it is that you can understand everything about it you can understand every single step like it's not that hard and I understand every single step of that and it means that I can teach you so if you have any issues with that you can ask me and I will explain exactly what happens at every single step which means that it cannot backfire it means that if you know what you're doing you cannot like get caught off guard with something not working and you don't and without understanding why and just randomly clicking things so don't randomly click things if you don't understand something ask me then drop me an email come to me because this is like the cornerstone if you understand this everything will become much easier especially everybody uses see make in the world like every like there are some companies that use their own system but there are so many companies that use see making so many projects that you see makes or you should use that but yeah I do get the point that from the start it can be a bit hard so I hope you got here an intuition you don't have to be able to write your own project from scratch by hand in C Mike so the only things you need to understand is that it here article it runs line for line and you need to understand what every of those lines does at least on an international level and it will come to you a bit later of why this whole thing makes sense I guess it's just practice okay I hope that you got an intuition here let's probably continue on you will have a bunch of practice in the homework so that's good right so I wanted to start with C make with simple seeming because we are now going to go into the more harder Simek and the start of it is that I want everybody to write unit tests like it's my mantra like I make everybody in the lab do that I like in the companies that I work they're always writing unit tests and that is the thing that makes people trust your code so if you don't know what a unit test is it's fine we will talk about it right now but we will start to kind of the rationale behind this why why should you even consider it at all so we will use Google test so it's a Google testing framework they used it internally for many years then they open sourced it on github and I think so there was a survey recently and 50% of everybody who uses unit tests use this system all the others are much have a much lower percentage it's a very mature system so you shouldn't expect any bugs in it if you feel like something is not working in this library it's probably in your code so the idea of unit testing is that you want to catch bugs as early as possible you don't want to catch them in a big system you want to catch them in a really small controlled environment so if you write your class you want to check that every small functions does exactly what your you're expecting it to do because if you don't check that and you include that class into some bigger structure of many classes and it does something wrong then you to catch what went wrong what was the cornerstone of your big error is really hard you have to dig deep into your code and find ok if I run this if I run that this like this value looks wrong but is it wrong and so on if you have unit tests you know that simple things work and this is a very important basis for your code I suggest for start to have some kind of feeling of how many tests do you need there is generally I mean it's a trade-off of how much time you spend in writing tests between and how much time you gain by not debugging your code endlessly and I would suggest for start to write at least two unit tests for every function so every function should have a normal path so what you expect it to do so say if I have a function that has to sum to positive integers for instance so it needs to like one of the tests would be to just throw a bunch of random integers into it and expect the correct results from it something like that and another a test case would be to test for extreme cases so if I if my so if I have some if I test some vector for instance try to pass like last element first element and so on so the things that can actually break the that can that are on the boundary of what is allowed in your function it doesn't it's hard to to tell you a good example without looking in the code but I guess when looking at like homeworks and so on you will kind of get that feeling and I want to stress it make writing unit tests a habit like it might be like some people are against it there is like a bunch of people who say hey we don't need tests at all but I believe that the majority of developers of professional developers in the world they write tests and they believe that writing tests is important and if you make it as a habit it will it will make your life less painful when something goes wrong because you will at least know what you can trust in what you cannot so how do the tests look it's basically they're defined still in a CPP file in within the testing framework and you basically define a so a dummy a test file would be something like this you you have this test word the key word you can think of it as a function it's actually it's a it's a macro but it doesn't really matter but what it does it generates a lot of code for you what you need to write is just this you just type test this is the name of the module that you test it can be anything like you can write test blah blah but it has to be something meaningful usually because you want to understand what you testing here and then you give some function name it doesn't have to be exactly the function name that you're testing over here it can be a bit different but it again it's just for disambiguating different tests so one test will have the function name the other will have function name two and so on they can also have like test function name for zeros or something or a test function name for once or something so it can be any name but the main idea is that these names have to be unique so the combination of these two guys has to be unique in all your tests and there can be as many of those tests as you want it to be so you can define many of those in the same file and they can also be pretty big so it doesn't just have to have this expect equals it can be you can create your object or create your variables do something with them and then check the results of your operations I think we will also go into some examples a bit later so the successful output of a test looks something like this so when you run your your tests you will get this particular pattern of of things so if you if it's passed like if all the tests that you've run past you will get the passed in the end and every test will have a run and okay so run is the start of the test okay is the positive end of the test so if it's if it didn't fail you will see this if it fails you will see the error with which it fails so usually you expect some value over there but it's not the value that you actually expect and that's why it will fail good so how do we add them with CMake that's why i started the whole thing with CMake so that we are not scared when we see something like at subdirectory and at subdirectory is just the same so it just happens to have a name tests here but it can be any name whatsoever the important part is the contents of this usually its tests and for the for the length of this course I urge you to use tests as you're testing folder I will expect that there is a tests folder in your code because that's from now on the way your code will be checked so I will basically inject my own tests into your project and we'll run your code against my tests right and that is what you will get in the in the output of your homework so this is important you will use it every time you need to specify to enable testing you need to tell it to see make and the good part would see make is it just text so you just tell it hey enable testing and he goes like yeah okay I will do and that's it so that's what you add to it and if you so in all of the virtual machines that I distributed to you there is the Lib G test the Dow dev is already pre-installed if you run your own system you need to install this if you're on a Mac you probably can also install it from brew or something like that what it does this thing is a bit different from a typical program that you install so typical program you install installs binaries of that of that program because of the way Google test is distributed this thing just copies the sources of the latest Google test into your into your system folders and you will still need to to create a library from them compile them and so on but we will we will come to that I think yeah I think on the next slide all right I guess we will spend some time on this slide because again like it's it's a bit bloated but the cool part is that all the code you need for you is for doing tests this is a real file from a real project and it fits on the screen of a presentation like I think that's that shows that it's not very hard and also it can be shortened but I think in this way it's a bit even more readable so let's start from the from the top if you if you add so what you need to do is now you have G test or Google test in your on your system it's actually in user stores so its installed in your system files and this is just a folder which contains the sources of of your Google tests and we can easily actually see it by going to to user source and if we go to G test this is the folder so it exists and the contents of this folder are just these so it's again it's a Simic it's a small C make project over there and don't look into the C make file C make list.txt and someone of that project because you might get scared because it was done to work on any system and it adds a lot of boilerplate if you want to you can look into it of course but it's not as simple as the ones in the course and if you go to the source folder of this thing you will get a bunch of CC which is just the Google's way of calling CBP files they just call them CC files I think it's just a preference of a company or personal preference but there are like some header files there are some CC files and these are the things that will be compiled right so it's it is a bit more difficult than what we did in the start of this lecture but it's essentially the same thing right so it still does the same thing it still adds subdirectory it does exactly the same things over there and what it does it it the only difference here is that we don't pass just one path to it as we did before but we pass two things so the second thing is needed to know where we want to generate our build files because if our if this folder is not in our project then we need to pass another folder where the build files will be written to and they will be written into the project binary directory which is usually our build folder and we'll put a G test in the end so that's where all the compiled all the compiled Google library will and okay then the next important line is include C test C test is another program it's just like C make but called C test and this is the program that you generally run to run through all your tests must be kidding me okay so with so okay so C test works with C make to run all your tests okay that's all you need to know about C test at this point then we have some we set a variable that is just a useful variable in case we want to change something and this variable is this test binary over here we just set it to a value of this we have some project name and this project name we just concatenate this part to the project name and we set it to the test binary okay so no magic over there and we can also just omit it and just use the same thing over and over but it's nice to define it once and then just use it as a variable right so whenever we use it as a variable something like this we just get that value over here good and then again there is nothing new it's just the same things as we did before but the only difference is that in in the libraries that we linked to it so we do the add executable we create a test binary from the test tool CVP which is our file where we set our tests and then we do the target link libraries of our test binary towards tools which is a library that we are actually testing and these are the libraries from Google tests they will always be there so these things will always be there this you will need to change whenever you define your own library that you want to to check and the only new thing here is that you need to add tests so add tests means that you communicate to see test and say hey this binary is actually a test command so whenever I ask you to run my test please run it like that's that's what it says and it says that okay well it's the name is going to be test binary and the command is going to be this so it's going to be searched in the executable output paths that we set somewhere and it will be a test binary over here this thing is completely compatible with the with the previous lecture so if you create a see make project just kind of copy pasting code from the previous lecture and then add this on top of it it should work right so how do we run the test now that we know how to configure the test we want to also run them because that was the initial idea and the cool part of it is that it doesn't change our process at all like we just do the same things we go to the project folder we do the build will do the make we do the see make we do they make and then we do one more step we do this see test - V V so V V is very verbose basically so you need to you want to see everything if you don't do it it will just tell you if the tests have passed or not but if you pass the VD it will also show you the output of every single test and that's generally what you want to have so that's basically it that's all you need to know to to write your tests and yeah so we can also do an example of that again life if you want to if that helps I'm not sure like does it help you when we do it like this or does it does it just make you more confused do you like who wants to see it live okay it's like ah okay okay let's do it let's just add things to our project that we already created okay I need to go to Tim C make project so we are back in our project that we had before sorry so this is our project that we started off this lecture from right so now what let's just create the tests folder so we created the test folder at this point and let's also do the add subdirectory add subdirectory okay and so again like this thing will work regardless of if I pass this thing over here it I can just use tests there so it's actually probably do it this way so that we are sure that everything works good now that we added this subdirectory we want to also create a cmakelists dot txt in the test because otherwise we will get an error just like we did before right so now that ok so what we need to do is we need to add a sub directory users source G test and let's project binary directory gee that's include ok so at this point we have at this point it will compile the Google test library and it will include this the C test so let's probably just stop at that and before test is very important we need to enable testing the only kind of thing that annoys me with this that it is not logical they never can remember is that you need to call enable testing from the top most seeming you cannot do it from the tests folder so you must do it in the top most seeming so yeah kind of see my lists okay this is like you just need to remember that I don't know why is that that way but so be aware of that okay so at this point we have a empty test testing suite so we can do the the C make and we can do make this make will take a bit longer than before because now it does the same thing as it did for our libraries but it does it for G test so it scanning dependencies of G tests building cxx objects blah blah blah and then linking a static library leave G tests dot a then it does the same thing for G test main and there are two files there is G test in G test main G test main is just the main function for Google test that's it like it doesn't have anything else to it so that's because they want to give you all the code just they don't want just to give you a library they want to give you a library and Anna main function to run this library good so now we have that and also you can see that another point that I made last time but now I think it's even better seen is that we do not rebuild our hello blah and bin main because they were already built we do not touch them this time so we do not need to build them again so make is smart enough to find out right we didn't change them so we don't need to touch them at all so that's what what is going on here good now now we know we want to actually test our library right so let's try to test our bla library it's very useful name for that we go to tests and let's let's just create a test blood dot CPP file right so in this test blood a CPP file we need to include G test jeeter's dot h I think if I'm not mistaken that is basically it just tells you that you want to use Google tests and then we want to include the LA dot H and then we can write a test so we want to test bla output tests whatever good so now we have some empty function over here and let's do it let's do a dummy test over here expect equals 1 1 right so it's very stupid like we just want to check that 1 is equals to 1 what do we have to do here is if we try to to build it now we will get we will not get an error why did we not get an error yeah right because we didn't add test blood to the to the see make so we want to we want to edit our see make in cmakelists file in the tests folder because now we have a new testing executable and we want to add that executable so we add an executable test bla and write test bla and we also need to specify that it's a CVP there is a test bla CVP file then we want to target link libraries our test block or test bla to G test and G test main and if we do that we still get an error I I believe oops now we don't why can you rerun it does it okay you did build the test blonde how does this is strange okay so let's see how our source a lot of H looks like as ah yeah because we never call this function so if we would call this function we would get an error because otherwise whatever we don't call doesn't have to be linked so you you don't pay for what you're not using and let's change our block to actually to have a some function again and then let's have a int a int B and let's go to blood or CVP and in blood at CPP now it's gonna be a sum and a in B and it will just return a plus a plus B okay and it should be not a void function it should be an integer function good so now we have this some thing and so the the semantics of this expect equals is you the first first to give a value that you expect then you give a value that that you give to it right so like that you are testing and for now we expect that the sum of 1 and 1 is going to be 1 and of course it's wrong so let's try to build that and now it should fail I'm confident 99% cool it fails because the yeah why ah now it now the main fails because the main still uses the old one sorry that it gets a bit confusing the problem was is that our old main function our old main function still uses the blah so we just remove it from here too to make sure that we don't have that issue okay now it fails with the error that I expected to fail with like now you have this linker error LD returned one and the problem is that there is an undefined reference to some and that is because with them we never linked our we never linked our library to to the actual test that we are running so we want to add the BLA library over here and let's also do the adds test just just okay let's try to make this one no okay cool so now it did build and if you look at our built folder with the contents of our built folder we now have the folder G test the G test folder is where our Google tests have been built they built files for the Google Google testing library we also have the folder tests over here and this folder test contains our new executable so if we just run something from tests there is a test bla executable over there so we can run it and you can see that there is a bunch of things happening over here and it has failed right so when it fails it gives us some helpful output like it gives us this that the sum of 1 and 1 is actual 2 but expected 1 and this is what you want so that's how you do it like you have a small function you write a bunch of tests for a small function you test every small public like every small function that you can get access to and and then you are you're sure that this function works as expected okay so I hope this is clear because we don't really have much more time on it now but again if something is not come to me and we will this that I want to talk about namespaces a little bit so we have actually seen them already whenever you use like CC out sea air and though you're using a namespace you're using the STD namespace you're using this STD double dot something but you don't like it's just because those functions are defined in the namespace you can also define your own namespaces so for instance there can be a module one in module two and they can have different namespaces so like namespace like this in namespace like this and the why people do it is because people don't want to create different names of functions so if I have a function print in my namespace I don't want it to clash with other print functions in somebody else's library and therefore and I don't want to name it differently I don't want to name it print my print my beautiful print I don't have something like that because it gets annoying it doesn't explain what the function is doing you still want to call it the way it is but you can put it in your own namespace and this way namespace becomes part of the type signature of your function and this way it doesn't clash with other function that is called the same name so it's kind of like it can look like this we can have two two functions we get meaning of life function and there is a fun name space in the boring namespace and you can use both of them if you want if you want to so we can call the boring namespace and we can use the fun namespace in the same situation and this will compile perfectly well because these functions are different even though they have the same name but because they are in a different namespace they are actually different functions all right we were using using namespace STD before and sometimes it's still fine to use it but never ever use that in header file because it means that everybody who includes your header file will be using namespace STD which means that every function from from STD namespace will now be a will now be populating your environment and we'll be able to call it without the STD prefix so if I want to define my own function C out for instance or my own vector for instance then I will not be able to do it because now suddenly its name will not be STD vector but it's going to be just vector all right so try to not use it and we will come to to the situation - what is - what can we do better with it so in this small example if we want to define power function to put something into power and we define it it just happened so that we define it in just the same way as it is as it is defined in the math library in the standard library of C++ and the problem is that we were using this using namespace STD so now we have a function power from the standard library and we don't need to use STD to call that and now it clashes with our library because we don't have a namespace for our library - and we will have a problem here so the output of this thing will be the call of overloaded power is ambiguous because the compiler does not know which function do we actually want to use do we want to use the one from the standard library or do we want to use our own because their signature is exactly the same okay I hope that makes sense generally a good idea is to use only what we need so don't use the world use something that we are actually using if we're using C out and ndele just replace you're using namespaces the D was using whatever you are actually using if you're using C out in this file say I'm using C out in this file and that will solve this particular issue because now power will have as like the standard power will be STD power and our function will be just power so now there is no issue and now the compiler knows that we want to actually use our own handwritten power function good so wrap up make use namespaces in your code so whenever you run you a project created in a namespace in the homework you will have a namespace given to you in the header file you will have to use it throughout your code and I think it's generally a really good practice whenever you define your own library wrap everything in a namespace you usually want a short namespace because it it creates a it's a very long name if you if you have a long namespace name and the namespaces can also be nested so you can have a namespace in a namespace in a namespace and I will not explain it here now but you can easily try it out so it's this is not too hard good also it's a good style idea to always when you create a namespace end it with this so put a comment with namespace and then the name of your namespace this way you will know where each of the namespaces end it will come handy when you have nested namespaces okay so the good way of using things is to call using my namespace some function or just use explicitly the function with the namespace so the way we do it usually is calling like STD see out instead of using STD see out and then just call in see out never use using namespace something in header file because it populates it to anybody who relies on your header file also try to avoid using this using directive in the header file - like it's it's not as bad as the using namespace thing but it's still kind of bad ok and just prefer using the explicit using so the kind of this using even in the CBP files even though you can use using namespace in the CPP file because nobody will include them it's still a better idea to not include the world if you if you are not actually using much of it good so that was a short thing about namespaces I think that was a appropriate time to do them the one more thing about that you can have nameless namespaces so if you if you write your CPP file and you find yourself that you are using some number don't ever use just a bare number in your code like if you want to say like your local variable will always be 10 don't ever write it in a function like I equals 10 or something because it's called a a hard-coded value and these are really bad so this is like the first if you look at the code and it's populated with hard-coded values it's a first indicator that this code is not written well don't ever do that if you need some constant that you will always be using and it should be local to your CPP file create an nameless namespace in the top of the CPP file and put it there so it looks something like this you can have a namespace it doesn't have a name and you have some some integers and flawed it can be any any possible thing that you might want to use the reason to do that is that because these variables will only be available in this CPP file within this small module they will not be propagated to anybody else so you will not populate anybody else's code with your variables that don't need to be there and you will also have a kind of a short list of everything that you are using on the top of your file instead of instead of hidden somewhere in your code alright good so now is a very very important topic it's we start with classes classes make us create new types because before we were working with like integer float and you know string and so on and actually string and vector are not fundamental types they're not defined in the language they are provided by a library they are just a class and this is what we will learn now ok so the idea of the classes is really really really important so if you did like you did Java you know what classes are and you probably know that in Java you cannot write anything not in a class right in C++ you can sometimes you have to so civil floss is not an object-oriented language it's a multi paradigm length language you can use any paradigm that you want and one of them is object-oriented programming but the idea of the classes is that they encapsulate the data that is why they were created it's like one of the main reasons of them and what do I mean by encapsulate the data it means that there is some data that is stored in a class and the only methods that I need to manipulate this data are also within this class so there is it never happens that I store something in a class and I process this with some other function in some other file and this is very nice to read in the code because if you open a file you know that whatever your store within this class will be manipulated exclusively from within this file and this is nice because you can get the if if something is wrong with my class that I've written I know where to look for the error it's always in this one file right and this makes life so much better and easier good so there are two key words for creating classes in in C++ their class of creating types their class instruct and the words type and class will be used interchangeably so they mean exactly the same thing in in C++ apart from okay not exactly the same thing very close to exactly the same thing there are fundamental types that come with the language and then anything else is a class so any other type is a class whenever you create a new class you create a new type whenever you create an object of some type it's an instance of a class so we will use this terminology throughout this course so we'll use class and type interchangeably for classes and I will use the instance of a class or object of a class for for an object that is created as a variable of some type right so the class looks something like this let's just dive into example first and then we'll figure out what we see on the screen so let's say we have a really simple image class and there are a couple of things to to see here so first of all every class starts with the word class so you write class then you type its name then you open a bracket and you have to close this bracket with the with the semicolon in the end if you compile your code with warnings it will actually tell you if you forgot the semicolon if you don't compiler code with warnings it usually works but sometimes it doesn't and then you will hate yourself so enable warnings right so there are public parts of the class and there are private parts of the class what does it mean public and private public is everybody can use it so anybody can see it anybody who can have an object of your class they can get access to anything that is under public what is private private is anything that nobody has access to so for instance if I create an image image and I pass this thing over here it goes right into here and then what I can use in this image is the draw function but I cannot call rows or columns and to call things of an object you use a dot so if I have an object I use a dot and I can use a function from within a class could say that was just like a small example to kind of get get us started and let's call it let's talk about the syntax of the class a bit in depth I already told you that the definition starts with the word class the classes can have three access modifiers so the private and public/private means that nobody ever apart from this particular class can have access to something protect it means that okay we will for now ignore protected we will come to that a bit later also I guess the most important words here are private and public because they give you the concept you want to protect access to something and you want to allow access to something else right for the sake of this particular lecture here protected will behave exactly the same as private public means that anybody can have access to it by default in the class everything is private if you do not specify any access modifier everything will be private and you will not be able to use this class it's a good idea to start your class with public always and then explicitly write private because it makes an explicit interface and usually people who read your code when they read your say header file with a class they will go from the top to bottom and they will start with public and the public interface is what they are usually interested in that is what they care about they care about how to use your class they don't really care about the implementation of your class if this class works well the classes can contain data and functions so just like we saw here it has some data there are two integers and it has a function draw right so that's fairly simple the functions can manipulate the data so any function that you call in your public interface can do whatever it wants to do with the private members of this class again like you access any member by a dot you could theoretically if I would put this into public I could also just access the integer value I don't have to call the function all the times but it's considered a really bad taste so don't do it it's possible to do it but don't the idea is that you always want to use a function to manipulate there are two types of special functions at least two types that we'll talk about more of them later but there are at least two types of special functions they're the constructors and destructors so every the life of every object starts with calling a function called constructor the life of every object ends with calling a destructor basically that's it like the and also name the classes in camelcase as Google style suggests right so I also told you that there is another keyword struct struct is actually a class but everything is public so strut can look something like this you have some values over here but you should never use functions in the struct unless you are doing some educational example and just show in some staffing and you don't really want to do private members so kind of in a tutorial to explain some concept it's fine but that's it like whenever you have a structure and you feel like you need to add a function to it that should be a class you can use structures still as simple data containers so if you want to wrap a couple of things together that logically should be wrapped together it should probably be a struct and this way you can also return something from a function so you know that functions return one one value right but you can return a struct which becomes as many values as you want it to be because you can pack them into one structure right okay cool so that's that's basically everything you need to know about the structures apart from how to initialize them the cool part about the structures is you can initialize them really really nicely you can use braced initialization and if we have a structure called named int let's say we want to name our integers and we want to print some structure like this we can actually now we don't need to create a structure than pass a constants to it and so on we don't need to do it we can just do it like this so it will be constructed in place and generally the compiler will be smart enough to not even construct it in place but just kind of inline everything and call it very efficiently but the syntax is clear right so you just use the curly brackets and you pass the values in exactly the same order as they are defined in the struct if your order is wrong your types will not match somewhere and the compiler will complain but that's basically it so it makes syntax very nice also you can use the same syntax from before returning from functions if you have a struct that you want to return from functions you can create all its components and then just put the curly brackets and put all them in a row and that's it you don't ever need to write the type of the function and it makes it really nice and readable but then again structures are really simple and they're just the container of the data the classes can store data of any type so it can be a string an integer another class it can be anything if we follow a Google style and I strongly suggest you to all the data should be private that is kind of the core of encapsulation nobody should have access to your data the only way people can have access to your data is through the functions that you give to them through your public interface because so say if I have a car and say my car is my class right I don't want people to be able to change the time of my clock from anywhere I want them to call the public function of open door enter the vehicle and then press the button so these are all public interfaces of the things that you need to do in order to manipulate some private data I hope that example was a bit clearer on the spot maybe it wasn't the best one but you can see the examples of this not in the code but everywhere in life most of the objects that we interact with have a public interface that we interact to and then we manipulate the private data our keyboard and a laptop is a public interface for us to communicate with say a compiler we do not change the bits of the of our processor on our own because we cannot do that because we have a public interface for that right so think about public interface as the only allowed way to manipulate the data that is stored in your class there is an important difference to naming the members the data members of your class their name just like any variable would be named but they have a trailing underscore in the end that is very useful when you are within a function of your class you want to make sure you want to know if you're working on a private member or not on a private member and for that you just kind of add this trailing underscore the data should be set in the constructor and if you have some data that needs explicit cleanup then you do it in the destructor for example if you open a file for reading like there is a in the standard library there is f stream that it's just like C out but or like C in but it works with files so what it does is it opens the file in the constructor and whenever it gets destructed it closes the file that way you can never forget to close the file you can never forget to release your resources and this is generally called resource allocation is initialization it's a very important principle better known as Rai C++ community really is bad in abbreviations every abbreviation that you know that you see in C++ will make no sense at all but it's a very important concept that you must remember and it kind of governs the way to think about the code so you need to make sure that whatever resource you acquire it can be a file it can be memory it can be anything is in the constructor on the moment when you create an object and whenever you destroy your object the resource will be automatically released so you as a programmer you don't want to think you want to be lazy and you don't you want to just do like code stuff in the way that you don't have to remember doing stuff right I want the ideally I would like to not write any code at all and everything would just happen magically right that would that's my goal so I want to write as few code as I can to make everything work reliably right the moment I need to remember something I will fail because my memory is really really bad and I will make mistakes I don't like that so that's why you use that particular way and it allows you to not think about what you're doing you know what you've done and it will always happen in the same way so this is a very important concept right so I basically already told most of the things that you need to remember about constructors and destructors but now let's talk about the syntax and what is required by the C++ language from you so every class has to have at least one constructor if if you don't specific if you don't specify a constructor so again like a constructor is it's just a so a constructor is something like this so if you have an image class there is a function that doesn't have a return type and it can take any number of inputs input parameters and it's called exactly in the same way as the class and that is your constructor so they're always named as the class and if you don't specify an explicit constructor a default one with no parameters will be generated for you by default so simple class we'll see okay well nobody defined a constructor I will just do a simple one that doesn't initialize anything it just creates an object and that's it everything stays in the in the state where it's uninitialized at the structure the structure for say a class called some class would it's very similar to instructor but it never takes any parameters and it starts with a tilde so you always started with a tilde and that is the structure and your your class can have exactly one destructor it must have one the structure and it and the maximum number of the structures it can have is one and you can if you again if you don't add one yourself one will be generated for you automatically and usually that's what you want you don't want to write your own destructors for many types I think in this course we won't ever need to write to write our own destructor unless for educational purposes that we can write one but the modern way of dealing with civil as class is you should avoid writing explicit the structures as much as possible so there are many ways to create instance of an object like let's let's do some example over here so they have some class it has a constructor this called a default constructor there are some custom constructors that take one parameter or two parameters and there is a destructor it's just for educational purposes you generally don't need a destructor but you might need some some of the Constructors so what you can do here is you you can create a default constructor to value so it the c++ will know which one to call just the way in the same way it knows how to call a function when you call something it will know exactly in the same way which constructor to call and there are other ways so you can you can just use the typical brackets and it will find out that it has to use that constructor over there but in C++ 11 you can use curly brackets everywhere and I suggest you strongly to use curly brackets everywhere so this thing is exactly equivalent to this thing the only small difference that makes it a bit better is that if I pass here say dot 0 that becomes a double and I need an integer and the compiler will not compile this and will say well I cannot convert like you are trying to convert a double to an teacher and this won't fly so let's just not do it and please make sure that you're using the correct type when you're doing it and it makes your code more readable and makes it nicer to avoid small mistakes that can cause errors also you can use the initialization like this you can say equals and then just a number of parameters in the in the brackets it's just a personal preference there is no better no worse here use the one that you feel that you like more right so the data let's talk about how can we manipulate the data the best way is to use to set the data in the constructor you should avoid having a function called set something because it basically is the same as just exposing it to the world like anybody can just set it or get it and that is usually not the best idea unless you're implementing something that mimics like a functionality of a vector or something right so if you a vector you might want to give access to a particular element or in an image you might want to give access to a particular pixel and you don't explicitly wants to know that somebody changed this pixel because you don't care but generally you want to avoid setters if we avoid setters how do we set the data well we do it in the constructor and the best way is to use the initializer list now the initializer list is this construction over here you use this color over here and then you basically initialize every every variable of those with a value that you pass in the constructor just learn the syntax the syntax is very useful and also you you have an empty function after that so this is the definition of the of the constructor it's not a declaration it's a definition at this point you and you can return data with getters like so if you need if your class has a property and so say I have an ID and I have a and I want to be able to query the ID and name but I don't want to allow people change my ID or name this way I I can create the Gators and the Gators have a different naming scheme they're not even though they're functions you can name them exactly as the variable that they actually return just without the trailing the trailing underscore so for instance for ID I would have the small ID and for name I would have a small name over here and a very standard pattern that you see is for big classes like string or something like not fundamental types you want to return the constants to a thing so in this situation we return a Const reference this way we do not copy the string to somebody else but we give them a constant reference so they still cannot change it but we don't pay for for for copying it so this way this return name will not return this string but it will return a constant reference to our name and this is usually completely enough for whoever wants to get our name if they just want to print it they don't really need to to have their own object of our name they just need to have access to our object and this way we give them constant access to our object now we come to cons correctness and cons correctness becomes kind of even harder than it was in functions so if you if you have issues with functions and using cons there it's going to be a bit worse here to start but then when you get used to using things correctly it will protect you from a lot of of errors that you might do you can mark a function as Const when you're using it so for example you can see Const over here after the name so Const after the name means that this function will never change the object it cannot change the object at this point whenever you use this Const whatever you do here considers all these variables as constant does it make sense so whenever you pass this Const after a function you cannot change anything within the object it's perfect for getters and so on generally prefer to to have to mark Const every every function that you don't expect to change the state of your object it doesn't matter if you need it because of of C++ but just think about it like does it make sense that this function should change an object if it makes sense that it should change an object don't use Const but if if there is no reason why it should change the object use Const so say something like print should never change an object or something like that okay and the cool part about it is that if we if we use this correctly then we by compiling our code we know that there is no mistake we know that we're not doing something that we don't expect to do so it's kind of a contract between us and the program and it's very very very very helpful I can't stress it enough the typical Khan starrer can look something like this so let's say we have a function print and we want we give it a student so we want to print the name of the student and we give it by constraints the problem here comes because we we call a name here but name is not marked as Const so it's not there and the problem with that is that is is that now the function can not this function does not guarantee that the object will stay the same and that causes a problem because we are given a constraints so we must guarantee that the object will not be changed and we cannot guarantee it because our function theoretically can't change an object right and the typical error that you can see is this passing con something as this argument discards qualifiers so there's discards qualifiers there are two words that are an indicator of an error Wisconsin whenever you see them it means you you definitely have a problem with constants right so just remember those two words right you can do everything else is kind of the same as with functions you can still declare classes and you can define them and you can do it in header files and CBP files and you're doing just the same apart from one small difference whenever you define a function you need to pass its name before the name of the class before the function and you can do it for any function like classes like like the constructors destructors or any other function that you might want but that's the whole difference I think I have like one or two slides more we're nearly done but there are some important points here so try to you can in C++ 11 you can initialize the members of the class in place so if I create a class I know a default value for it it's a good default value and it always should be like that I want to have a class student and you have earned points and you have happiness and I want like to initialize your earn points to zero and your happiness to be in one for instance right that's what I expect my class to do whenever I construct an object with a default constructor so now whenever I construct it with a default constructor I don't get uninitialized values I get values that I know what they should contain right and this is a really nice thing the only pitfall here is you cannot do it with structs if you do it with drugs you lose the ability of passing them by curly brackets so don't use it in structs anyway instructs you should always initialize everything and you should only use structs only with the initializer list like with the with the brackets so you can use classes as modules so every class should encapsulate its data and the methods to to work on this data and usually the way they are separated is you put some class in a header file and you have some class that's EBP to implement that it's just the same as with functions but now you have a single class per file so in your one header there is one one class in your one CPP there is a definition of this class okay so we're done a bit over time but I hope some things were clear today you can read about cons correctness in the CBP like the one of the big C C++ sites and also you can read how to use the Google tests in depths if you want to add their page I'm sorry I had to shorten the Earl because it didn't fit on the slide okay so thank you and sorry for being a bit late yeah
Info
Channel: Cyrill Stachniss
Views: 16,578
Rating: undefined out of 5
Keywords: robotics, photogrammetry, C++
Id: q8xO2eJijy4
Channel Id: undefined
Length: 105min 25sec (6325 seconds)
Published: Wed Apr 18 2018
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.