 C++20. I'm afraid this won't be the talk that Armin is hoping for, so this won't be a grab-back of tips and tricks around C++20, but just focusing on one kind of tiny new feature that they added there. When I reread the paper that introduced that feature and the the motivational section introducing it that got me kind of an ah-ha moment that that feature got added exactly to make me happy. So I'll just delve into that that tiny part and there won't be any spaceships or modules or concepts or anything in here. I'm sorry. So that tiny feature revolves around my obscene obsession with our string classes, as you might have guessed. Because yeah, what what do we have there and and what pisses us off is what we want is these wonderful plain old string literals that you have in C that you all know and love and what we have is something that at least by now on the syntax level looks pleasant, but at the on the runtime level is still a complete disaster. So with a with a plain string literal you have that in the read-only data, so row data short for the data that doesn't change that comes with a with the executable where there's no runtime cost involved, but with our string classes, these O string or U string stuff, what we have there even if it is written as just a string literal beyond the scenes at runtime. We copy that over so we create a or need to allocate something on the heap, copy the data over, set up this reference count, which is expensive to modify at runtime. Telling you how many pointers or how many users of that single string there are which is important which is expensive because it needs to be multi-thread safe. So this is we don't want that. So we at one point started to with C++ 17 we had the possibility to use or to introduce these string literal classes which are a bit better because they use constexpr to add compile time, generate this layout and we do a bit of a hack there because we have this this reference count which would need to to be increased and decreased all the time when you create new copies of this which doesn't work because it's in read-only data but we already had a flag there telling you that this is a static string that will never go away. So we won't need to increase and decrease the reference count because it will never reach zero anyway and if it didn't if it did we wouldn't throw it away so that saves us here that we have this this flag in that in that word and Yeah, that's a bit better but it still sucks because what we want is at the top No, what we want is at the bottom what we have is at the top whenever you use these less expensive string literals You need to give them a name. You have to reference them by name. They have to be L values You can't have temporaries there. You can't have our values what we want is actually something that You just write down the string and then it magically gets created at compile time in the read-only data Without you needing to introduce a variable that names that string because you don't want to Repeat every string with a variable with a name that mimics the string because you're Yeah, you have 200 strings in your in your file And you don't want to introduce 200 variables for these strings that will be ridiculous But that's what we need to do if at the moment if we want to be fast We have to go with this ugly String literal that we don't actually want So What saves us here is So-called non-type template parameters, which are not a new thing Which are used every day already in the the OU string literal From the last slide is actually also using these template parameters so you can have templates that don't only abstract over types but also over values until C++ 17 these values could mostly just be integers So you can have an array class or an array template that you instantiate for different sizes of the array and the size is given as a template parameter So that's not new stuff the new stuff that comes in with C++ 20 is That these non-type Arguments or parameters that you pass in into the template No longer need to be just integers, but now also can be classes themselves so we still have this array with a int non-type template parameter and then we have some function f that is also a template function and that takes a complete array as It's argument and this is whatever it wants with it. I'm not specific there I'll clear that up later and and and the next trick is that This is not actually a type array is not a full type because array is parameterized on its size but We don't need to to when we specify this f template We don't need to specify a complete type there. We can also deduce the actual type that is used So this is this in the next line this function f gets called With an argument that is an array For because it's a string literal with four bytes Including the trailing null byte so the compiler is smart enough if we tell The compiler that f is a template that takes any kind of array Regardless of what the actual Argument will be for the for the array template. It will figure that out by that by itself. So it's smart enough for that and this is What will what will save our day for our ugly? string literals and We're still kind of restricted with what kinds of Classes we can use for these template arguments there They introduced a new or invented a new Kind of Class types they call them structural types Including that they can only have public data members So we had to to to make some data members public but so what so this is not a restriction that hurts us in any way And with that to da we now have a template string literal operator function that is That takes an old string literal we already we already have that we already have a way to translate a raw String literal a C string literal into our old string literal class which has the right layout Which is done at compile time and we can take that beast that class instance of an old string literal and pass that Into this function and what does that function do it wants to return a old string? But it can just return the old string literal that we have because we have an implicit conversion constexpr implicit conversion from old string Literal to old string and with that what the only thing we need to do there is the string literal that we take as the argument for this Operator function at the template argument. We just return that and with that to do we have now a Function call or whatever we we wherever we take in one of our string classes. We can just write down such a Literal and that's not only for old string, but of course also for all you string The Microsoft compiler has a bug so we needed to have two different underline old string where this underline you string names for these two and the the Our you string literal one takes then UTF-16 string with a with a you prefix there, but apart from that they're the same the same underlying technology and This is finally fully constexpr so we can finally have an array or a traditional C C++ array of three Differently a different length string literals of Our oh you string literal classes that are generated at compile time all placed into the Text the row data of the executable zero runtime overhead The other thing that we needed for that is the second C++ 20 feature that I'm That I'll talk about here very shortly is this For this for the for the upper one to work to be to to actually be constexpr That the destructor also needs to be constexpr now because we we don't invoke the Destructor because it's read-only data. We never modify that But the the standard still mandates that if you have constexpr Data that the destructor also even if it's not called Needs to be a constexpr, which is now cheap to do because in the case That we are in a Constable that we do have some something Constexpr that is generated at compile time Then there's a new function to test whether this code is executed at or at compile time And if it is we just don't do anything and if it is not if if we are at runtime if we have a different kind of String that was actually constructed on the heap Then we do what we ever did just Decrement the the ref count That's it And to prove that this actually works and From from these very lengthy identifiers you will guess that Probably we'll have another instance of our famous breaking tool chains Since whenever because now we pollute our executables with all these I mean all these all these All these template arguments these OU string class literal Instances that we now have in our code. They somehow need to be represented in that Executable and they're represented there was with very very very long Names that encode their actual content and yeah, it it saw this little R that you see on the that an M instruction so with the new compiler these are prefix with this that TAX these symbols and all of them are Marked as are there, which is read-only data Even not exported so they are hidden inside the inside the shared object and don't incur any runtime relocations Which is important as well but I Gave that a try Converted with a clang rewriting plug in lots of our string instances into these wonderful new string literals Only to find the test executables then to To fail during shutdown because what happens we have all these wonderful static data all over the place We have these also modules things that load shared libraries And we have these also modules that are destructed and runtime because at exit because they use because they are stored as statics and what a what an awesome module does at When you destroy it again Then it deal closes the library That it references and when you deal close the library then the mappings of the library go away And we have now these pointers from other statics We now have this point these pointers to the strings that we use from there but we still use from there but The memory is gone for the string because in the in the past these strings were created on the heap and Lived as long as we reference them, but now we cut that through once we Close the library from which they come from which their row data Comes and now we run into these great issues where it shut down We yeah Chase pointers that are no longer valid and crash one solution The underline exit to not run the destructors of all the all the static data But that's Checking out we don't do that What I do for the moment is now to disable the deal close in the other module and the tests pass Hooray short commercial break. So how close are we? very close until or For a long time we have this with the latest C++ Opt-in thing. So if you build with that then whatever your compiler office C++ 26 by now from some of the latest compilers We use that for for compilation. So whatever we have in the code base that wouldn't be compatible with C++ 20 Has long been cleared out by those people are me who routinely build with that opt-in flag then I did a Gary change to to actually in Configure in our configure script a bump the baseline to only allow C++ 20 on your and ran that on Jenkins And all the bots were green. So all the compilers we use there Are already fine with using C++ 20. Thanks to cloth recently updating The Linux baseline Because in updating the Linux baseline. He also thankfully updated from GCC 7 to GCC 12 and Hooray GCC 12 is near enough To fully support this We do have an hour read me We only mentioned for example Xcode 14 whatever Xcode 14. I assume the Jenkins bots are using the latest one as well for the Microsoft compiler So it might be that with a very old Xcode 14 or a very old Microsoft 2019 compiler we would run into issues. So we would need to update our read me to to tell people You need to update your version of this compiler, but this it's not You don't need to to internet to to to bump your compiler baseline in any way And you just need to to update to the latest release of Compiler you're using so we can Do the switch now and enjoy this And that's it modulo the missing coffee, but I Hope it works out. Um, yeah clang is I mean we have the the Jenkins clang version is What was it? I don't know, but it's new enough as well. So you're also updated clang to request clang 12, I think so and Even older clang would would pass anyway. So that's that's a fine one as well Again what I didn't get your last part I didn't measure that in any way because the bill takes so long anyway So I have not done I was happy that I got the the unit tests Working now and I'm refining my rewriting Clang plug and to do all these modifications And when I have I mean I already have a quite a substantial amount of of modified of changes That still works I didn't measure but I could measure of course. Yeah, that's that's one point And if I if I even I didn't the latest version I didn't test them on on Microsoft yet so I'm not sure where we hit this limit of Breaking other people's tool chains So it might be the case that we can't rewrite everything with the plugins But need to be a bit more conservative and in places where we have Performance improvements from from using these no longer initialize them at runtime we can use them And in other places use them not maybe if we run into these issues, but yeah, I'll provide numbers before I Flip the flip the button