 Yeah, hi So good news and bad news Bad news is David burn is not here. He's not gonna sing for you Good news. I'm not gonna sing either So Shamelessly stole their title from an old talking hats record, but I'm gonna talk as you might expect from me about C++ So Yeah, the the usual Where are we in our? endeavor of Keeping up with the C++ versions in our LibreOffice code base There's Hasn't been that much activity Recently, so we're still since 5.1. We're still with the same Tool chains that we support as the baselines. That's GCC for seven and the Microsoft 2013 compilers We've kind of reached I think we've kind of reached a spot there where the compilers are Good enough to support many of the things But we actively use in the code and there's not that much But we desperately long for that will be available if we if we bump the baseline. So we kind of yeah ran a bit out of enthusiasm to push further Because every bump of baseline, of course means that somebody feels left behind or some some things that some Machinery that used to work needs to be updated as well or wouldn't work anymore. So If you look at the features that we don't have yet where we would benefit from the 2015 compiler or in some cases, they wouldn't also be supported by GCC for seven and would need for eight If you look at that list, it's mostly things that we've kind of covered. So for example const expressions we do have a configured time check for those and Then have macros around features where we benefit from from having these available in the code But in a way that if they are not available on the compiler then the code still compiles But maybe does something compute something at runtime that it would otherwise Compute at compile time. So there's not much lost there the the the rest qualifiers on the functions That's mostly a feature to to catch Uses of like when you use a function that modifies the the the member function that modifies the object and you call that on a temporary and The effect of modifying the temporary is get log got gets lost afterwards That's a buck in your code and and you you you misuse that function and didn't notice We can catch those With ref qualifiers and we do in some cases And that only then warrants on the compilers that we use that threat safe statics. We have this ugly RTL static stuff to cover these for the micros and still use that on the Microsoft compiler So that's all things that We would benefit from them. We do benefit all the way from them. So there's yeah We'll keep it at that the one thing that we might find interesting in some places is that our Unicode or our Unicode string support we have that cell Unicode type def Which on platforms that do support native Unicode utf 16? Type the car 16 t type We use that one internally now on Microsoft We still use that w car t thing internally So if we had uniform support for these Unicode string literals for the you In front of the string literal then we could do In some places we have Non-asky string literals in the code that we want to represent represent in some way So what we do there now is to do a static array of cell Unicodes and then Put in the individual characters there and use that in a few places We could use a more Allegiance syntax there, but that's not that many cases of places in the code and for a single string for single character things like if you had some place in the code that wanted to replace that P in a circle With the text you could you could already use that Syntax that I put there and and and that works already so Yeah, as I said, we're kind of Reach the reach the spot where we are quite comfortable with for the for the moment and maybe even for the foreseeable future Unless somebody gets enthusiastic and wants to bump baselines again So that's 11 and 14 Next standard that's coming up will be C++ 17 which is already quite Stable and finished and the assumption is that compilers will pick that up More or less quickly and especially some of the Sugar type of Improvements there I want to go through some of them because Compilers will probably pick up the more trivial or more easily implemented sugar stuff Fastest and it still can can can bring some benefit to how we write code so one is this new syntax The problem is you have a we have a function that returns Multiple things like if you have a container and you insert you call the insert function Then it returns a pair of the iterator Where it got inserted and a Boolean flag whether it actually inserted it or whether the element was already there And then the iterator will point to the existing element So there's a new syntax now to bind multiple variables simultaneously to the return values of a function This could return a pair or it could return a tuple or it could return an array even so there's and and there's also you can also use that with some some way with With your own classes you can declare how your class would be Destructured into binding to multiple variables But this is kind of like the the most the most simple use case for it You have a pair that gets returned in the old code That is down there You would have used first and second to operate on the members of that now you can give them give them easily used names This pairs nicely with an next New feature which is initializers in if statements That's similar to how you can declare variables that are local to a for loop Now you will be able to do that also for if and for switch statements so that You don't pull you the out in namespace with having these names that are only useful within your your if Like for example, if you pair that with a with a decomposition Destructuring bindings You see how how elegantly you now Declare some variables Then have the test on that in that one statement and inside of that if block You can use that So assume that all that all things that will come more or less quickly To a compiler near you One more thing is the context expression if feature Where I Yeah, look for an example that we actually have on the code that will benefit from that and I found one that is Yeah, maybe not the ideal example, but but it does show the benefit Of these but the the idea is That you have an if expression in if statement That is evaluated at compile time and Where only one of the two branches that the branch that is actually taken needs to be Meaningful both of them have to be syntactically valid because the compiler of course needs to parse past the closing record of the other branch but the It doesn't Go into that branch and doesn't look into it more closely so for example the code below at the bottom is We have some place where we do some Template trickery on on different Kind of kind of enums with their underlying types and they could be signed or unsigned and we want to check whether some some actual value is Non-negative so for the case Where we are unsigned if we would actually write Value greater equal than zero then the compiler would warn That this is non-signed so it would never be Less than zero so we would get a compiler warning so to avoid that warning because we want to be warning free of course So what do we do? We do some even more heavy trigger Trickery on on top of that with standard enable if stuff so we have two functions Actually the one is only enabled if if the type is signed and then we do the actual Comparison against zero and the other one is only enabled if it's an unsigned type and then we always return true because it can't be negative That's much more intuitively written with a constant expression if thing where you actually see what's going on instead of having this Plop at the bottom where you have to decide a What's that all about and and then it's something trivial as you can see in the upper code block So that's always already also something that will much improve readability of the code so next thing up is That as of lately We have a new Garrett Jenkins a billboard so whenever you commit some patch to Garrett then different Jenkins bots will test out try out your your patch see if it compiles see if it doesn't produce any warnings we had bots that run on on on Linux on Mac and on Windows what we didn't check so far is the Linux with Clang and all the plugins compiler tool chain and Our our plugins are very picky by now So it often happens that people commit some patches that have Sometimes trivial sometimes not so trivial issues that the plugins warn about the Clang plugins So what we now have is a fourth bot that is triggered on every Garrett patch submission That is now checking that patch on The plugins that the Clang plugins build For now that means that there is for every Jenkins report for your Garrett patch. There's two lines of Bills that are triggered and when you click on the one for the the Garrett the the the Clang version Then you get to a page where it where the where it says default Which is a bit unlucky because you might get lost on that page But if you if you click on that default then you can go to the to the output So if it says that it failed then you'll need to to hop To get to to why it failed Norbert he's not here at the moment I think he told me that he'll improve that so that we are again back with a with only one Status report for all four bots So that confusion will go away, but I wanted to show it to you what it looks like today so that you're Not confused by now having two lines of success or failure mails for your Patches so if you do get a failure for that, please do look Do these hops to see why it failed? Oftentimes I said it's trivial things like there's a plug-in to check that you didn't use the null macro But instead use C++ 11 null pointer or there's a plug-in that checks whether a Trivial function could be member function could be static So these are also easily fixed then there's more beefy ones like one checking for misuses of VCL pointer stuff Where you can? It's not okay for example to do these on on heap On on on the stack to create them on the stack and stuff like that so we check for that So if there's any if any of the reports that you get You don't understand or don't know what how to fix them I think you'll always reach somebody on the mailing list or on I see to to Clarify that or to get that sorted out, but please do look after them because otherwise when the Once that they hit the master Then the next person who submits a patch of course will run into the same Built breaker because the master is already poisoned So After this I come to the second part the food part is actually about a shooting in your food with C++ always a favorite never going away and I once again have a look through our commits and Code and identified some of the more amusing things that you might want to look out for One is the auto thing what's bad about this? Little piece of code where somebody Reroge existing code to use use the new for statement The range based for Where looks good is it good? No What happens is that we? Create a copy for every iteration through the loop Because what a map? Begin So so what happens in the in the actual for loop is that you call from begin to end You get the iterators into the into the map and then work on them Name this our label and what you actually get back is Not a pair of a yo string and a yo string But a pair of a key and a value and the key is always const so that standard pair is Different from the standard pair that we have up there. So the compiler internally creates a copy of that Because you can you can implicitly convert from the from one to the other, but it needs to do a copy conversion Create a copy a temporary for that So this code above is actually quite suboptimal Is that But I guess I was understandable anyway good So the easy fix as always is don't specify your types because you typically get them wrong So just use an auto and and everything is soft and there's no there's no issue Something also to do with Containers something amusing some amusing you syntax and c++ 14 that is is So-called transparent containers you might never have heard of them before The problem is you have some Structure or some class that you want to use in a set and each element of that class already has a defining Some identity like you have a string that represents it and a unique string So you don't want to have a map from these strings to these items because each item already contains that string So that would be cut off redundant. So you use this set of these items But then how do you actually access the element from the set with a given identity So there was some very funny code Some old code in there that Went to great lengths and I distilled it down to to what it did It defined one static object of this item type and whenever you wanted to search or search the set For for an element you you only have that find function on the set that takes an item You don't have a find function that takes only a string So you had a static why it was static I don't know but it even adds to the fun of of how Over dose that was so you you have a static sign the idea to it and and then you Use that one item To search in that set of items What you of course do in C++ 11 with that is That you don't use find where you have to put in an actual item object But you use find if where you specify the condition What the what what on on on on a feature of that item only and you specify that You find one where the ID matches what you can do with C++ 14 is Something that looks very funny. You you change your set To be a so-called transparent set and you do that with that funny little syntax there So if you ever run across that syntax and wonder what that means, that's just What this is it's so-called transparent containers. So what that does is the find function Whatever you put into the find function needs no longer be an actual object of type item But it's just some arguments that are forwarded to the internal comparison function. So what this find actually Does in code is of course at some point it needs to compare an element in the set with this argument that you pass in and you use The perfect forwarding internally for these arguments And they are they are used to actually compare So if you then also define the necessary comparison operators between an item and a string both ways then those will magically work and No longer need To create an item just for the sake of searching for an item with the same ID So this is just Once more Another thing that happens Sometimes but for which luckily at least clang I think this is a clang warning that gets emitted. So we don't run into these This is a case of Creating an object and Then returning it By value So a unique pointer in this case gets returned by value from the from the function and there's this Return value optimization so that you don't create Additional copies of it when you return it out. So Per standard the there there should be some some Copy when you move it out of it, but you can you don't the compiler doesn't need to to emit that copy and construction actually So you can you can spare a copy there, but By Chaining this old code to use unique standard unique pointer Probably before that it used a pointer or something a naked pointer something the person who did that Accidentally inserted a standard move there because may probably because they thought Unique pointers always need to be moved But what happens in that case is that that doesn't Buy you anything so there's no advantage in having a move there, but it also Passes your code by formally disallowing that return value optimization So because there's now no longer only the name of a local variable that gets returned out Standards as you can't Elite the copy construction. So this is sorry. This is actually not making the code Better in any way it makes the code worse So always always in return statements be wary of using standard move because it never Improves things and typically Makes them worse also in the cases where you return a temporary But as I said, there's a compiler warning for that so at least with one compiler and Any questions am I way too fast way above So I come to some lighter part now some some fun trivia At the end Quiz time so kind of virtual function be defined as deleted Do you think does that make any sense? Opinions a clear maybe yes, yes it can actually I Doesn't make any sense. I don't know it actually also doesn't Result and I thought maybe that would result in a in a in a class with with no v-table Just the RTTE information, but actually at least the the GCC and then Clang ABI does have a slot there To a to this deleted virtual Stop that then upwards your program if it should ever be called We can extend that to kind of pure virtual function a Pure virtual can it override a non-pure one? Does that make any sense? Undecided as well. And so yes that that works as well and That one actually could be useful because there's some places in the code where we have virtual functions that Should never be called and we have some asserts in there so we could either make them pure or or deleted and That could actually be used to clean up a few places in the code that it