 The wild To start with Ivan Chukic will I Got it. We'll talk about new features in C++ 17 and 20 And then we will have a talk by the sponsors followed by the Oscars or the Academy Awards So it's a pretty good lineup. Let's begin Okay, this was a real really enthusiastic introduction. It will be over soon So Let's first the reason for me giving this talk I usually don't give over review talks because I find them boring But the main reason is that in KD especially KD frameworks. We don't even depend on K on C++ 11 so I this is my attempt to try to a Little bit inspire you to force People like David for now called the David 5 to actually propose for us to increase the compiler requirements for most of the things that we are doing so The usual disclaimers blah blah blah The history of C++ was really slow first it was see the classes and we all know that it was standardized in 98 and since then until C++ 11 and nothing major changed we got an intermediary New standard which was just the bug fix release of the previous C++ 98 So for the most part the language was really stagnating a couple of things were published under the technical Whatever was One which had a couple of interesting Experimental library features and stuff that you could access through STD column column tier one column column something like bind or similar stuff But nothing actually happened Nothing important until C++ 11 now C++ is split into two parts the core language and the libraries and usually when we say a new Version of the language most of the people think only about the core language and What new syntax we are getting most of the people just somehow ignore the standard library? Especially in cute community Some people even claim that they never needed anything in standard library Some of the cute maintainers which I'm not going to mention so In C++ 11 We got in the core language. We got lambdas Auto range based for loop and in the library. We got a lot of things including smart pointers In C++ 14 we didn't didn't get that many new things just again a polish of the previous release with a lot of bug fixes Now C++ 17 Has landed or almost landed. I'm not sure whether it actually is published by ease or not But all the features are already known and and voted in So we kind of know what we are going to get One of the first things that we are going to get are structured bindings So we have a lot of things in standard library which return STD pair for example when you want to insert a value in a map You're going to get an STD pair of an iterator and a boolean whether the insert was successful or not And if you wanted to use it in the old C++ You would have to write something like if where dot second and if you just Look at the line if where dot second. It doesn't mean absolutely anything It doesn't tell you a single thing about what you're doing there so The thing that we were able to do since C++ 11 is to declare iterator it and a boolean value called success then called STD tie STD tie will get create a tuple of those element references to the elements that you passed it and then you could write STD tie equals to something that returns a pair or a tuple and The result will be decomposed into the variables that you tied now this is Much more readable. You can just write if success and you know that something succeeded. It's not called the dot second But the problem is that we still have to declare the variables completely separately from the tying and Value assignment the problem is not only that it's tedious to write But we can't declare these variables as const and we are advised by the Scott Myers and a lot of smart C++ people that We should always declare everything as cost unless we actually intend to change it So this is again not an ideal solution. It's better than the original one A little bit more readable, but it has a lot of boilerplate around it So C++ 17 is going to abuse yet another set of brackets So instead of using curlies or normal parentheses there For this the angle ones are used What does this mean? We are creating two variables that will have their types deduced by the compiler and The types of them were will be the same as the types that are in the tuple written by insert Okay, so this way we don't need we can immediately declare them as cons They will get the automatic automatic types and we kind of get something that was Always possible in many functional programming languages things to the decomposing structures like this and This is one of the let's say biggies in C++ 17 Which kind of gives you the idea that C++ 17 wasn't really a big Big step forward compared to the C++ 14, but we will return to that later The next thing that was introduced This is probably the code that you all Wrote at some point when you want to to lock a mutex Obviously, you're going to use RII with some locker guard or something and then you're going to create a block So that you minimize the portion of your code where the mutex is locked and Again, this block exists without any without a while without anything It's just there so that we can invoke RII when the block exits Instead of this now The if statement and the switch statement support initializer then semicolon and then the The value that is going to be checked against true or false just like the for loop Okay So now we actually have just a single block The lifetime of this lock guard will be only in this if and obviously in the else branch But since we don't have the else branch we don't care about it This variable doesn't even exist outside of this block. Okay, and this is again something that Makes the code a little bit shorter and much safer because you cannot Even if you try you cannot leave that mutex on unlock mutex locked And then if you want to combine the previous two features Because we had the code that did an insert and then checked for success You can combine. Okay this structure this pair into it and success and then the Condition for the if will be just success So while this might seem like a really useless feature to add to a programming language and Into the major programming language and major version of a major programming language. This is quite useful and In a couple of things that I actually could use C++ 17 in I abuse this as much As possible it make the code much shorter in in a couple of really important situations so That's essentially it for the part about Major let new language features Which I consider at least important one of the things more that was Inserted is to help metaprogramming not regular programming So for imagine we have a function f and it needs to access Accept a value and we need to have different implementations for f depending on whether that value is integral Value or anything else. So for example in con char or whatever compared to strings or everything else in old C++ we would need to Create two different implementations. So f impulse Which accepts a value and accepts std true type and The other f impulse accepts a value and std false type and Then what would f do f would call f impulse for a value and then it would Pass a compile time type or a compile time Integral constant is integral of t will return Either an instance of true type or an instance of false type and the correct one will be called and This is something that is usually called tag dispatching because this true type and false type are essentially tags That we are attaching to a function in order for the compiler to know exactly which one to call In C++ 17 we are going well we got Something called constant expression if the difference is that normal if the thing that you pass as the condition is Evaluated at runtime with constexpr if it's evaluated at compile time and If it's true, then the else branch is discarded completely if it's false Then the if branches discarded completely this means that both branches obviously have to have correct syntax but they can use things for example if We got the else We could call For example else if the type is a string we could call methods of a string The compiler if this was an ordinary if Would complain that for integers that member function doesn't exist and this way That branch will just be thrown away and it will never be called So we can write things that are Syntactically valid, but our would be invalid in the context when T is some specific value some specific type So the if constexpr is something that was There was a more powerful proposal called static if by Alex and rescue The idea was to allow if constexpr to be anywhere in the scope so that you can enable disable functions and similar things but because of concepts and Little bit of a clash between concepts and that static if was Abandoned and constexpr if was added just for the intermediary period until we get concepts Okay, the next thing that I really really really love Again about generic programming until now if we declared the template function We could call it just with f of 42 the compiler would automatically deduce the type of the argument So we wouldn't have to write f of t of int close and 42 but for classes we didn't have automatic type deduction So if we tried to write C of 42 where C is a class template class We would get an error and For this reason for example in the standard library. We have a std pair Std pair if you want to instantiate we either have to write std pair of int char something something Or we need to use the make pair function because the function can invoke the automatic type deduction and The class cannot so for most of the template classes that we created We always needed to create a make that class function to trigger the automatic type deduction with C plus plus 17 The compiler became much smarter It now allows the compiler that the standard allows the compiler to check for the constructors and To see whether it can deduce the types from the constructors themselves So for example for the pair we don't we will not no longer need to specify the types The compiler will check all the constructors for std pair. It will see okay. I've got something that's called t1 t2 I can match t1 t2 to int and int in this case And this is something that is really really removing the boilerplate for writing make something make something make something make something Apart from these there are a couple of other core language features that were that have been added for example guaranteed copy elision Who knows what the copy elision is then Okay, I don't have really enough time, but if you are returning of some complex I don't know a string from a function and you have a string in in the caller and you're just the sign in it The compiler will move Not move we'll elide the copy of the result into this one, but it will directly construct the result into the caller and This is how this is an on the optimization that was always defined by the standard as optional For a lot of cases now. It's a bit of compilers are guaranteed to make it so you can Start to rely on it more heavily Then we have to play total which is Inline variables are cave. I'll skip that as well attributes there there have been Two important attributes at this far as I'm concerned Fall through is the attribute for example if you're writing a switch statement and you forget to write somewhere return a value or Break the compiler will now report the warning unless if you explicitly say that you want a fall through to the next case and Since I've seen so many bugs For people forgetting the break or a return. This is one of the really really really good features The other one is no discard You can declare for example a function like STD async which returns a future Do you know what happens if you call STD async with For example STD async this function STD async this function STD async this function and all of those functions should write Hello world character by character What is going to be written on the on the screen? That's what normal people would expect. Yes Unfortunately louder Yes, so STD async returns a STD future a special variant of STD future which Blocks on destruction and since we didn't assign anything to a variable After each STD async call the temporary future will be destroyed it will call a dot get and it will block So even if you write a thousand asinks everything is still synchronous For functions like those you can just write no discard and then compiler will complain if you Actually discarded the value instead of storing it into Instead of naming it somewhere or passing it to another function We have nested namespaces Which is one of the reasons why originally Qt didn't want to use namespaces So that they don't need to deal with namespace a namespace b namespace c and stuff now It's much much easier to write a column column b and we have a little bit relaxed range for loop a range base for loop in C++ 11 and 14 For both begin and end of a collection you have to have the same type now this This restriction has been lifted so that we can support special types for the end called sentinels Which is really useful with ranges and stuff that actually use sentinels, but for normal collections. Maybe maybe not if you if I have the time in the end to explain what sentinels mean in This specific case you can just remind me Now we are moving to the library part We have been added a couple of Algebraic data types more specifically some types got into the standard library The first some type is optional of t Which is something like a container that can either be empty or have a single value inside So in our original example names dot insert just imagine that if insert fails It returns a false and an invalid iterator, which is a lie, but imagine and We are only considering the case where We are going to access the iterator only if the second thing is is true and this is something that is Really really often done If we wanted to have an optional value in C++ we either created a pair of bull and something else Or we created an iterator Sorry pointer to something which could be null or point to a real value or Some really demented people use lists because lists can have zero or one item And we are going to ignore that they can have much more than one item So in order to model something really trivial, I don't have a value I have a value we use the really really strange hacks the problem I think the most common was With the pointers and the beat the pointers you don't know who is the owner Do you need to delete it when somebody returns your pointer or not or it's just an optional value that Oh for the love of God Okay, I don't have the time So we got the optional you just say optional for iterator. It can be empty or it can have an iterator and if It's true. So optional casts to a boolean, which is true if it has a value As an extension we have a variant Instead of not having the value or having some value. We now can have any of the specified values inside So like a type say if they tagged union Where this is quite useful for For example in optional, we just know that the value doesn't exist But we don't know the reason why it doesn't exist So one of the really common use cases for Varianties to say okay, we have a value or we have an error message So whether it's a error code error message or a pointer to accept to an exception it's quite useful and if you want more about this you should check out a Effective error handling or something like that from cpp on a couple of decades years ago In order to access the values inside of a variant you can if you're sure that some Some type is currently in a in a variant. You can call as did he get If it's not there it will throw an exception and you can call if you just want to check whether the type is there and Without any exceptions you can call get if It will return a now pointer Yes, instead of an option it returns a now pointer to but who cares Now as did he get he as did he get if are not really the best way to To check what what is inside of a variant you should always use the STD visit And with C++ 17 we can easily create overloaded lambdas. So you have a rudimentary way to do by pattern matching You say visit overloaded for if We have an iterator call this lambda if we have exception pointer call this lambda and this Looks and works really nice visit will return the value returned by the lambda that that has been called So it's not void it can you can really nicely chain all the all the invocations Again if somebody wants the explanation of the grayed out part I'll I could rewind a bit later And we have STD any which is not to be used and then we have Instead of using const string graph and similar things in all of the places We should obviously use string view which is able to abstract over blah blah blah I think we had a talk at academy about string views. If not, it will be at cute developer summit or Whatever, so you can check that talk instead And we had a couple of really amazing features Again library features for people who write generic code and for example, you're writing your own algorithm like copy if One of the argument arguments that you're going to get is a function Now it can be a function. It can be a function object It can be a pointer to a member function pointer to a member variable it can be an object castable to a function pointer or something like that and Yeah, I think I managed to count them all So for the most part you can call them as f of open parentheses argument close parentheses But pointers to member functions and pointers to member variables You cannot call with a normal function call syntax and Because obviously the language wasn't extended to sport it the library guys decided okay We are going to do it because these lower level guys have just done So they implemented a function called sd invoke It gets any kind of callable so anything that I just enlisted and a list of arguments that you can pass to it So if you're writing generic code, this is the way you should invoke your functions It looks ugly, but it works for much more than normal function call syntax Then we have sd apply which does almost the same But it doesn't get the arguments one by one but inside a tuple and we have type trait is invocable If you want to write meta programs and check for whether something is invocable or not We got a really cool thing C++ 17 introduced a lot of cool things into the library in the core language not as many five minutes okay, so The Academy Awards is cancelled So If you want to do static introspection in old c++ it would be really really long and not understandable And now it's a little bit shorter and still not understandable So we have we can create a type trait that checks whether Some type has a column column value type nasty type So most of the collections in standard library and Qt has it so that you know Q list of t that it contains t and We can check With void t we can check whether some type actually exists If it doesn't exist then the thing where you use the void t will be removed from the overload set So if we are going to pass t is an int The first one will pass because void t is empty So by default it will be false type If it goes to the next one it will check do I have int column column value type? No, I don't it will remove that from the overload set It's not a compiler error on anything else. It's sub substitution failure is not in RSV and then you will be able to use it Has value type as an any type trait from the standard library What's more void t can even be used to check whether expression can be evaluated on a certain type so if This worked for collections that are well behaved and define value type This would work on any iterable object So we need to have a begin that we call can call on the function We need to be able to the reference begin and that's the star begin off the global of t and We need to have the end iterator Which will never be the reference so we don't need to start it and we don't need to check whether it can be the reference so we here we check for a t type t is star begin off of a value correct and is end of Star off that value correct and again you can call it as any ordinary Type trait and now in C++ now in C++ 20 we are going to get ranges Algorithms have their problems with composibility. I'm now speeding up because I have only three minutes for three huge features So algorithms are cool to compose in a completely wrong way not in the right way so we are going to get ranges and Instead of having temporaries and stuff You can just say copy items remove all the items that are selected and push them to Output stream iterator to print them out and you can chain these transformations. Just like you are in a normal functional programming language And with a much nicer syntax than SQL What's the problem here? Yeah Although the compiler will not really say that it will say a lot of a lot of a lot of a lot of error messages And one of them will be that you can't That there is no operator minus on list to iterator because it's not random access But that's something that you need to know. That's not something that the compiler is going to tell you Concepts which are implemented in gc trunk and you can play around with them Instead of writing template type name something you write template Concept name see and then when you try to call the function It will at compile time check where the dead type satisfies the concept in front of it Okay, I'm going to skip this a bit You could write your own concept For example this concept checks whether something is callable so that you don't need to accept functions as ordinary templates But you can communicate which is which are the arguments that you require and you can just say Concept bull callable will be defined as invocable of RFRX dot dot value and blah, blah, blah You all know what this means And when you define a function you can just write callable of bull comma P and this is still a template. That's one of the problems Template is not written. So it's implicitly template which can lead to problems for people who are writing libraries But it's a template. It's not a SDD function. This is not going to be any slower when executing the code It's a normal template. It's just that it's checked for P to be exactly something to satisfy some condition and Then you all know what futures are You all know that it's a real problem to call dot get because it will block your system Some futures have a dot then to chain the continuations, which is cool, but ugly and Qt has the most ugly solution of them all Creating a future watcher that you can connect to and the last line is missing You need to set watcher set future this one and this is how you change continuations in Qt which is So one of the proposal that that is most likely to get into C++ 20 needs to introduce two new ugly keywords one is called co-await and the other is called co-return What this is doing? For example FV is a future value It will suspend the current function until that value arise. It will not suspend your main program So just temporary pause the function and continue working on everything else and Then you can have a couple of co-awaits for each of them It will be suspended until the value arise until the value arise until the value arise and Yes, a couple of Sentences more The thing to notice here is that we are returning a future Since we have a function that is going to be suspended and its call or expect it to finish immediately It cannot actually wait. It needs again to return a future So co-await and co-return need to Can be used to change stuff. You cannot ever actually return on your normal value until you call a dot get but most of the time you don't need it and It doesn't need to be used on the synchronous stuff only you can use it on any I'm not I'm going to say monads Like optionals so instead of checking if Not to value return you can just say co-await optional value If the optional value is not there it will just jump to the exit and return and not an empty optional Otherwise value will get that value process it and return an optional that has a result in it and With just two minutes over the over the limit. I'm finished