Empirically Measuring, & Reducing, C++’s Accidental Complexity - Herb Sutter - CppCon 2020

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments

Hope this proposal doesn't get stuck in the process for 5 years because it seems to really simplify the language. It also makes it safer by enforcing additional compile time checks which are possible only when the intent of passing is known.

πŸ‘οΈŽ︎ 11 πŸ‘€οΈŽ︎ u/tpecholt πŸ“…οΈŽ︎ Oct 11 2020 πŸ—«︎ replies

Yeess!! I want this.

As someone who only tinkers with C++ now and then, coming back to the language and having to remember all the crazy incantations for references, r-value references etc twists your melon. I am never completely confident on what I am doing.

I have got nothing against ampersands but something like this would be soo much better:

void myFunc( in string input, inout string result )
{
    // blah
}

Whats also of interest in Herbs code examples is that he got rid of the const identifiers as well!

...of course, by the time this makes into into the language I will probably be retired!

πŸ‘οΈŽ︎ 7 πŸ‘€οΈŽ︎ u/masterofmisc πŸ“…οΈŽ︎ Oct 11 2020 πŸ—«︎ replies

Okay. That seems like a really good idea, and I have discussed similar things with my colleagues for quite some time. We can see similar approach in other languages, too.

Now, the problem I have with it is, that for in/move/forward parameters, it really IS important, if you are dealing with a reference or a value. Cause if it is a reference, the value underneath can be unexpectedly changed by almost any action.

Let's take the simple example, push_backing into a vector.

With the new syntax, I believe the method signature will be: constexpr void push_back( in T value ); Now, even though it's not visible, we CAN be dealing with references. Let's consider a common problem: if we need to relocate the vector, and the passed element is part of the vector, we need to take care of that, and push the last element first, cause if we move old elements into new buffer first, we end up copying a moved-from object.

The problem with marking parameters "in" that I see, is that in templated code (or if the types can change the way they are passed), our code can work for small trivial types, but break for anything more complex. With "in" parameter we need to always worry about the same thing as with references, and the code can work differently depending on provided type.

I see it as a problematic inconsistency, and a pesimisation of sort, cause if we'd be to completely remove the references, there would be no way to specialize a function, on whether the parameter was passed by value.

These are some thoughts after looking for a way to simplify passing arguments myself. I don't think these problems were mentioned in the presentation.

I don't know how valid these points are - maybe I'm missing something. Still, it feels like it takes away a lot of control over what is going on within our program, and it can bring any kind of surprises.

πŸ‘οΈŽ︎ 7 πŸ‘€οΈŽ︎ u/KaznovX πŸ“…οΈŽ︎ Oct 11 2020 πŸ—«︎ replies

In the Q&A Herb said that we can completely get rid of references with this. And for parameter passing, sure, maybe. But what about reference members? What about references in ranged for loops? There's at least a dozen other ways to use references. Or is there something I missed?

πŸ‘οΈŽ︎ 5 πŸ‘€οΈŽ︎ u/boredcircuits πŸ“…οΈŽ︎ Oct 11 2020 πŸ—«︎ replies

A few thoughts.

First, I wish he had explained move and forward better in the talk; the paper does a much better job justifying why they exist.

Second, out parameters and errors don't go very well together; you need exceptions, including presumably Herbceptions (a paper I'm surprised he didn't mention as being related). Because what happens if an error happens and you can't fill the output parameter? Now you've violated the rule that it must be initialized. Even if you're fine with exceptions, not every place that an error appears is a good fit to report that error by an exception, so in such a case are you just boned with out? From a semi-related question during the Q&A it sounds like you'd just have to resort to inout, but that seems like a major loss. It'd be nice if there was a mechanism for somehow designating the return value of the function as an indication as to whether the variable was initialized. For example, suppose that for a function returning an std::expected that out meant "if the return value has a value, then the parameter is guaranteed to be initialized, otherwise that guarantee is not met". You'd probably want some kind of customization point so it's not just a single type, and it'd be good to handle the case where there's not a return value other than the error code itself.

Third, there was a Q&A about virtual functions, and Herb said that they'd have to match. But I see no reason they couldn't be made contra/covariant (as appropriate for what is being annotated) -- so if a superclass has foo(inout string s) then subclasses should be able to restrict that to foo(out string s) or maybe foo(in string s). (I think -- thinking about whether those relationships are actually properly variant is making my brain hurt. The second of those, overriding an inout with just in, would need a different calling convention than just in to match the superclass.)

Fourth, I really wish both talk and paper had more actual real examples of code instead of mostly just fs.

Fifth, the paper mentions an optional rule (inspired by, e.g., C#) of marking call sites with at least out or inout to match, so your call would be std::vector<int> v = uninitialized; foo(out v);. I really really really hope this is allowed or even required. ("Allowed" presumably would mean "would be possible to require for a project via clang-tidy rules or whatever", so that's fine.) I could stop arguing for my semi-unpopular opinion that one should pass out parameters by pointer instead of reference so that there's an indication at call sites that something passed as a parameter can be modified. (Edit: This point I added later, but I could have sworn I had there before... I guess I deleted it?)

πŸ‘οΈŽ︎ 6 πŸ‘€οΈŽ︎ u/evaned πŸ“…οΈŽ︎ Oct 11 2020 πŸ—«︎ replies

This is the best C++ proposal I've seen in a while. This will make C++ even friendlier than Rust.

πŸ‘οΈŽ︎ 3 πŸ‘€οΈŽ︎ u/lookatmetype πŸ“…οΈŽ︎ Oct 11 2020 πŸ—«︎ replies

One thing I believe C++ gets right and other languages get wrong is object identity. An object of some type T is uniquely identified by its address. This is apparent when passing function arguments.

// I have this arg all to myself
void foo(T arg);
// Someone else can see this arg.
void foo(T& arg);
void foo(T&& arg);
void foo(T const& arg);

In my opinion, the fact that other languages (Java, Python) do not have this distinction is a mistake. It makes programs more difficult to reason about, not less.

For me, the proper way to pass arguments to functions is eminently clear - either by value, or by reference with the correct set of permissions.

What do the in, out, and inout qualifiers gain that me that is worth the cost of giving up control over object identity?

πŸ‘οΈŽ︎ 3 πŸ‘€οΈŽ︎ u/Zcool31 πŸ“…οΈŽ︎ Oct 12 2020 πŸ—«︎ replies

I am heavily invested into high performance C++ and so I am always afraid that new C++ standards might take away some old fundamental functionality (like pointers or pointer arithmetic) which would cause a lot of work for me and maybe even make some performance optimisations impossible.

However the changes proposed in this talk would be welcome in my projects: I had to implement a nasty pod_vector this year because std::vector does not support uninitialised memory allocations. Also the in, out, inout, ... parameters wouldn't cause too much work for me. Generally I am fine with deprecating old C++ (especially from the STL) if this does not deteriorate performance.

πŸ‘οΈŽ︎ 2 πŸ‘€οΈŽ︎ u/Linoliumz πŸ“…οΈŽ︎ Oct 12 2020 πŸ—«︎ replies

So I had a quick play with the compiler extension and I did manage to crash it:

void move_in(move auto a, in auto b)
{
    copy_from(a, b);
}

int main()
{
    // history prefix
    String s;
    move_in(std::move(s), s);
    // history suffix
}

The good news is that it's crashing on a pathological example, and that makes me happy. I'm curious to see if such an aliasing fault could come about when using the parameter attributes consistently.

πŸ‘οΈŽ︎ 2 πŸ‘€οΈŽ︎ u/KazDragon πŸ“…οΈŽ︎ Oct 16 2020 πŸ—«︎ replies
Captions
welcome everyone to the final session of this all new all virtual cppcon 2020. i hope you've enjoyed the program as much as i have and we're now in our final set of talks so here's what to expect most of it's happening right here in this all of room or equivalently if you're in the overflow room you'll see the same thing for the next hour or so i'll be giving this talk and then right here stay right here for john cal who'll come in and he'll give us the conference wrap up including some interesting tidbits about next year and things you may not have known what you can do with this conference still and what to expect and then we're going to come back and use the rest of this half hour here for q a for my talk so this talk will have q a but and it'll be all in this room so stick around and after john we're going to go up to the hour to do q a after that you could either hang out here and listen to the final set from the jim bass night band the cppcon house band thanks again to them for playing for us this week from the seattle area or you can go to a zoom meeting if you're interested in planning or maybe interested in wanting to contribute to cppcon or just see the ideas that are going around or give feedback you can find the zoom meeting on sked that will be happening at 1 500 denver time so that's what's going to happen for the next hour let's talk about actually measuring stuff because every single one of us knows c plus plus is too complex that's a given but that's qualitative it's not quantitative and yes we can all give examples and experiences but that's also not quantitative i can't count those directly wouldn't it be nice if we could count it and also see how much is accidental that is non-essential complexity so let's define some terms and give some motivation complexity matters because as long as any system is more complex than we need it to be we are paying taxes using it and it may not seem like a huge tax on one day or on one week but as we keep paying it it's going to keep on costing us as we read and write code as we deal with bug reports and outages and even vulnerabilities and exploits as we wait for our tools as we have to teach people so we can benefit from reducing complexity in these and other ways so for the first part of this talk i'd like to give a shout out to barbara mcclintock she is a famous scientist a nobel laureate who was famous for actually looking to see what happens in dna and showed dna transposition and how that worked by empirically measuring so let's do what dr mcclintock did and empirically catalog classify and count c pluses complexity well how are we going to do that first let's remember what fred brooks distinguished as essential versus accidental complexity essential complexity is inherent in the problem domain so if you build a systems programming language say that values efficiency and it wants to give modern abstractions like the kind we're used to any language regardless of the syntax or the details is going to have to expose something like compel-time polymorphism something like virtual function dispatch so there are certain essential things or encapsulated types and the details can vary from one to the other but there's going to be some essential kind of abstraction in solving a given problem that no matter what the detailed solution is you're going to find it where we all trip up and every language does this is the accidental complexity it's where this particular solution boy it sure has more knobs or it falls over or the knobs come off at our hand sometimes we have to jam it back in more than we would like it to and more than it needs to and we'll call that fred calls that accidental complexity and it's an artifact of this specific solution and i'm giving you the picture of a push sign when you see a push sign on a door when you see a sign on almost anything that tells you how to use it almost certainly there is accidental complexity and there's a ux problem as well but there's something that doesn't work like is is easy to learn like you would expect it to and often is more complex and then accidental complexity enters the picture now the reason i mention signs is because signs often tell us where the accidental complexity is so if we could count the signs for c plus plus maybe we could count the accidental complexity in an empirical measurable way so i have bad news and really good news and they're the same thing c plus plus has probably the largest the richest body of coding standards and guidance on how to use of any programming language i haven't actually counted compared to other programming languages but it's popular and it's complicated and it shows in all the stuff that we've written down to teach and learn so i've actually gone through and counted so far in what's on the left hand side and i'll continue on the right hand side to actually for in each book and this has taken months and months of work spread over years to catalog what is each piece of advice so in scott meyer's items it's not just per item each item may have several guidelines to do this don't do that or do this a certain way and now by getting a list of rules we can now make a spreadsheet which i did thank you excel and start to quantify it and to classify it so the first thing i did was to classify this these catalogued rules the first granular level of classification was are they language or library rules most of them were about the language but there were some about the standard library we'll focus on the language rules here i also found a few that i'm going to discard because they're general rules like for instance use a version control system okay that's good advice but it's not specific to c plus plus or programming languages in any way not even programming you want to do that for word documents so i'm admitting those and 10 were even in my opinion you may differ just wrong rules and but even them i found informative because often they arose because the language created a pitfall or a confusion or an ambiguity that somebody resolved in a way that i happen to disagree with but it wasn't only their fault it was because there was a complexity so let's look at the language rules of the 533 individual language rules i classified i then went to see which ones are accidental versus essential and also which ones can we improve on because even essential ones we can improve on i found that over 360 were accidental complexity that another language like c plus that solves the same feature could do in a simpler way that didn't have this problem that c plus has that we have to teach and that we're improvable because look here's how it could be done in an existing or hypothetical other language there was a way to do better i found that almost 150 were essential that is you're going to have something like this in any language that solves this kind of problem but we can still do better it was needlessly complex the the knobs were too ornate or there were too many of them and finally i found 25 that were yes you would pretty much have to take this guideline out of this c plus plus book change c plus us to c sharp or something like that and you teach it almost verbatim with just minor changes like that and c pulses does in fact have such beautifully designed features at least those 25 rules fall in that category now the first thing i want to point out just from the shape of that pie chart and its proportions fred brooks also famously concluded there was no silver bullet there was no single thing we could do in technology or he also included management techniques that by itself could give you an order of magnitude a 10x improvement so we often quote that but it's worth looking at why he said that that's the conclusion but he also states like a good scientist his premise and his premise right before that was how much of what software engineers do now is still devoted to the accidental as opposed to the essential unless that's ninety percent you can drive it to zero and you won't get a 10x improvement but if you remember the slide we just saw if you do have 90 improveable accidental or improvable complexity then you have a big problem but you also have a big opportunity and that is where we are we have such an opportunity where by evolving the language we could in principle address this much just because by cataloging we've measured this much is accidental or improvable essential bjarnus truestrip has famously said for some at least 16 years now since design and evolution of c plus plus that in fact this is could be possible an equivalently powerful language that is good at all the things c plus is good at but is simpler could be done about 10x smaller and notice what he says it would be through generalization which is absolutely true and i would expand on that a little bit by making general orthogonal features that compose well so you get maybe fewer simpler features but a combinatorial explosion of things you can express and that's where your expressive power is retained and it's also by making those orthogonal things directly express what you're trying to do usually instead of how to do it which is usually a messier recipe so let's pursue that thought and when i went through and i took a first cut classification into major categories of these different sources of complexity that we could improve by far the biggest one the category was multiple ways to say the same thing so c plus is famous for this kind of thing but then as we go through there are a few other large buckets that we can address the one at the bottom right kind of class authoring convention so that's the subject of a different talk i've already given at cppcon and the meta classes paper directly expressed in the intent for how we write a class but we're going to focus on different ones today so with that breakdown we commonly hear siphos is too complex and what i've tried to do is to empirically catalog classify and count so it's no longer anecdata or just anecdotes but we can actually say okay c plus is this much more complex and i think that we could empirically make the case that bjarna was correct and is correct when he says that c plus is about 10 times as complex as it needs to be for various reasons backwards compatibility and other things but that's a statement that bjorn has made qualitatively based on his deep experience and that i think is directly supported in the empirical cataloging that i've been doing so now we're going to switch to a different kind of scientist and the nice thing about mad scientists is they have crazy ideas and every so often at least in the movies they can build a flying time machine that looks like a delorean so we are in this mode where as c plus developers so often we say well yes but we can't really do anything about it we can only make incremental improvements so let me in the rest of this talk try to demonstrate a 23 and then when you add it to meta classes a 30 reduction which actually gets us one third of the way roughly to a 10x improvement and what i'm about to show is experimental but we're also going to see prototypes in godbolt so when we look at this picture that we just discussed and we focus on these two wedges of the pie about 23 percent of all the guidance that i've cataloged so far have been about how to pass parameters sixteen percent and how to initialize variables seven percent now some of it's repetitive because it turns out that multiple books talk about how to pass parameters but that in itself is an indicator because we don't have to dedupe these rules the mere fact that other books continue to give the advice even though it's already in print and they often don't give the same advice but they give divergent or incompatible advice then we haven't we have a measure that this is something that the community has voted with its feet to say here is what is important to teach about c plus so let's talk about first how to pass parameters here is what we teach today i i it's it's too much to go into it i'm not going to spend a lot of time on it we'll see it sort of as we go with the today examples but i'm going to focus on the simpler thing that we can do in the future but this is roughly what we teach today and it is not complete if you want examples of where it's not complete i have a link to a github repo that i've just published that contains a draft paper about this material and compilable links to examples you can try on the working implementation but if the paper explains more about why even this is not complete that's because we are saying how to pass parameters i'll pass this one by value pass this one by reference so what kind of reference should we use we're we're specifying the recipe not the intent if we could enable expressing the intent what do i want to use this parameter for then i could teach i believe just this and if this were added to c plus then i believe that this is fully expressive and fully subsumes what we do today in the use cases i've seen so far and i would never have to teach anything more than this now there will be more code than this in the rest of the talk but most of what comes up in these next slides is about explaining the complicated thing we have today because that's what we all know and are used to and to help see how does that relate to this proposal the this proposal parts the code will always be simple the what we do today that's equivalent is more complex but i think i can teach parameter passing in this slide by what's shown here and get rid of roughly 23 of today's literature if only we could do that but let's dig in and see well yeah this is too simple and in just says give me an x i can read from in out and x i can read and write out is an object i will write to specifically i'll assign every that's how we say assignment is to set all the salient values of or one i'll move from or one that i'll forward to other code and that's it and one question i've received is ah is this exposing implementation detail no except what's necessary for the contract with the caller because this is information both the caller and the callee need to know for instance of the call site will there be a side effect on my argument oh i'm passing it to an in parameter it's going to only read there will be no side effect through that use of my argument i'm going to use some terms definite first use of definite last use through the rest of this talk here is explaining them in one slide let's say i have a local variable parameter includes a parameter and i want to say what's the first use of x on any execution path through this function what is definitely going to always be the first use of x and that's easy it's in the very first line you can't execute non-exceptionally through this function without going your path going through that line of code first and seeing that as its first use of x so that's a definite first use of x where's the definite last use of x well there are two and that's okay because any execution of this function will take one branch or the other and if it takes the first one then x dot hold is the last use of x that it will encounter in this function and if it takes the else then the c out x is the last use in that function definitely if you get to that line it's the last use of x there are no more what about y y doesn't have a definite first use because if you process y well you might do that on some paths and then it is at first use on that path but it's not definitely always going to be a first use it does have a definite last use and that is transfer y with that in hand let's start defining in in out out move and forward the five things i think you need to know to do all parameter passing in c plus plus the most complicated as it turns out and we'll demo at the end is in so what we teach today and what is automated here in this abstraction in the language is if the type is cheap to copy like an int then pass by copy that's what we already teach people today we just say in do that all the time otherwise pass it through an indirection as if by pointer or reference so that's the calling convention if you cracked open the assembly you would see a value or essentially a pointer an address on the stack what can i pass to the in parameter any initialized object can be an l value or an r value inside the kali i can treat it as a const l value because it could be it could be constant on cons the argument but in says i'm only going to read from it so i treat it as a constant value as const for my purposes that's implicit except that if you passed me an r value then any definite last use that tries to copy from it will treat it as an r value in other words can move from it let's see how that works so today we would pass in by value this is what we teach people today f1 takes an int an in end pass it by value oh it takes an in stood string or something else that's more complex oh well then take it by const reference and if you're going to take a copy and move is cheaper for that type you want to optimize for our values that also overload for our value reference and by the way remember to write stood move on that and remember to write student move only once on the definite last use of the parameter so that's what we teach people to write ad hoc today if you write a template it's harder i'll show you what you what you could do and what's a very a very small number of people like standard library implementers do to follow the advice oh ift is small passive by value et cetera mostly we just say hey template yeah cons construct sure let's do that there are a few who say by value and that's a discussion you'll see um senior address in my very first cppcon keynote 2014 so you can find that on youtube but mostly they just say ah construct because it's hard to overload to pass by value you have to enable it for requires to do that and it's even harder to overload for r values but i'll show you how you can pretty much do it all of these equivalently in this proposal you would just write in in int is all you write and it automatically passes by value in x if x is not cheap to copy automatically passes by as if by constraint and if you give it an r value argument at a given call site we'll move when it calls g and the same thing is true of a template i don't have to worry about if it's a template i don't have to specialize i don't have to enable if it requires anything whatever the type is this is what in will do so it's efficient we're always going to copy values when that's cheap and we're going to move from our values and it's easy to write and get that effect so that was in now let's talk about in out this one's actually pretty simple for in-n-out we just pass basically the address of the object so that we can read from it and write to the original object in c2 there we could actually and we're contemplating pass in and out by value as well for this as an optimization you'll see that mentioned in the paper that's a possible extension but right now the paper says that we pass by pointer you have to pass an initialized non-const object so that we can write to it and then we actually will treat it as that non-const object you just use it as you would normally but we can also give you a rule because you said i want an in-out parameter we can now tell you if there's no path in the function that ever writes to it that's not what you said you wanted and we can give a diagnostic so that because you've expressed your intent we can give you a higher quality of code where if it compiles it does what you said which is the holy grail of programming languages if it compiles it meets my expectations so today we write in out as basically x ref sometimes x star and in f1 we're fine we read the value that's fine we write the value that's fine but in f2 we forgot to write to x and today we don't get an error maybe your static analysis tool will give that and turns out you'll see on the next slide you spell it at the out parameter exactly the same way so we can't distinguish between in out and out unless you're using static analysis extensions that put annotations like in out and out and these exist and are used to disambiguate this that the language does not but in out this is what you would write and this is the simple case where the proposed equivalent is just a instead of that ampersand just write in out but it gives you more than just a nicer syntax if you don't like ampersands it also makes sure that you do assign to the value and it's simple and clear because now i can distinguish this from out so that's really all to say about in out as i can read and write from acts but what if it's only out pretty much the same except that i require that every path must have a definite first use that assigns a value to x and remember assignment and c plus plus is our typical way of saying right to all the salient parts of or passes it to another out param because this will compose and that will do the same thing so today we can we can't say out except as a comment if we in the first line g of x happen to read from the input value uh that kind of works even if the input value is garbage or sensitive data somebody's password we can do that even because we can't say out only directly and we can't flag that we've failed to actually do the out part either to write to something unless we have a tool that gives a warning because and that's non-portable because we have to have a non-standard out annotation and a tool that knows what we mean because in the language we can't express this the proposed equivalent is just to say out it would be a compile time error therefore green green isn't is for errors when the errors are good and desired you would get an error if you try to read from x before writing to it you are required to write to it and then it's okay to read from it because you're reading a value you set you're not using the the in value which you said you weren't going to use simple and safe and clear move also passes by indirection actually in the implementation this one has already been optimized to also pass in say by value so if you say move int it will actually do it into by value under the covers and which is an optimization of what we do in c plus today for for move templates and what we're going to do is require that this r value we accept only our values and that we pass them to another move or our value use so today the way we write this in a non-template is to say oh we use a r value reference which is spell double ampersand when the type is not a template parameter type it's a concrete type then it's an r value reference and then we remember to write sub move if you want to move a template parameter type well you can't just write t reference because that actually means something different than c plus plus sorry so what you do i won't go in the details of why but thank you nico yosudas for teaching me this incantation it turns out that the incantation stood is reference v happens to be the right thing for you here to say accept only our values just trust it and then instead of to move yeah you really should be saying stood forward and then you have to explain why you wrote that instead of move because you're really doing stood move but this is pretty close it's not exact an exact way to write a move templated parameter in c plus plus because you didn't actually write move but it's very close and i believe this is correct today but i don't want to teach that i just want to teach template non-template don't care big type small type int don't care just write move and they all work the same finally forward again take this one takes any object just like a perfect forwarder today but is much easier to use than a perfect forwarder we're allowed to look at the value if we want to read from it say because maybe if the forwarding function we're writing code that's that's in the middle between a caller and kali it just passes things along but it may want to look at it say to log the value that's what we commonly do in forwarding situations so we can read from it const uses but every definite last use is going to like today's perfect forwarding pattern preserve the const-ness and whether it's an lr value whether it's a temporary or not basically so today the way we write that is the forwarding pattern which looks like this for a templated type that's fine now if you want to do this for a non-templated type you still have to write a template because that's the way you write a forwarder in c plus plus and then you say through requires or enable if you say well it's got to be an x and there are different tradeoffs to say whether you say is convertible or is same and if you say the same you have to say remove cbref because you just do but this is how you would write it for a concrete type which as far as i can tell nobody does uh nobody uses this to forward concrete types it's difficult but it's just possible here in this proposal it's easy i just say forward the type it doesn't matter whether it's a template parameter type a concrete name type and i don't have to make it a template just to forward something if i'm forwarding a concrete type this is by the way really important because you'll have noticed that several times now with move especially and before but also within when we overload it with move i've said today we have to write a template sometimes or get out of a template sometimes instead of writing the code normally and bjornis truster has long made the the the important stake in the ground that he would like to see less divergence and a convergence in regular code and templated code and to remove the differences this helps directly to remove the differences between writing a template and writing a non-template code and makes them the same so i do agree with that that's important so now having looked at those let's look at some examples and you can find these at cppx.godbolt.org which is graciously made available by matt godbolt thank you very much matt and the person who's done the hard work of implementing this as well as several other of the proposals i've spoken about here at cppcon you can find thanks to andrew sutton and who has done the implementation of these parameters in particular so let's now switch to these examples and as we do that i wanted to show you a couple of helpers first so the first helper you're going to see me use sometimes in the body i'll want to say and let's say we copy from this parameter so i'll just call copy from here's a really simple way to write in c plus 20 write a function that just takes any number of parameters and just copy constructs attempts to copy construct each one and of course if it gets an r value it will move instead just take a variati generic set of variables by value that's all that does auto dot dot dot each variable each parameter can be a different type it's auto and it's passed by value kind of nice i want to see what's going on i want to see where the copy constructors and the move assignments are in particular so what i've just put together as just enough to get the testing done is i've got this global history string just for the purposes of the sandbox testing and i've got a function which will again it's using c plus 20 code it will take any functor any invokable thing by value and it will run it but first it will clear the history and then it will this thing will as a side effect write things into the history and then we'll return for convenience the history that was generated from running that f if you haven't seen this syntax before history equals brace brace that's the a modern way to say default initialization because well that's how it works so i find that very useful so that just clears out the string runs it and returns the history that was generated by that execution and now in order to see the copying and so forth i've got this noisy helper which just basically writes out to the history string when you call the default constructor destructor copy move copy move and otherwise just delegates to the thing you wrap so that way i've instrumented the special member functions so i can see what they're doing and i can then write test cases which you can find in the github repo you'll see the link out at the end so here's the first demo this is the really simple one we hope that there is nothing magical to see here all it's saying is today old we say pass an individual in oh you passed that by value and then when in this new proposed way you would say in int i we would hope the code gen is the same so let's take a look and here if we look in god bolt there's our copy from helper here is old in it takes an int by value just the way we teach people to write it today and you'll see here is the code gem push call pop new in which differs because it's using this new in implementation now it's an in in so it ought to pass it by value the code gen in this case is the same push call pop so that's a good thing that's the first demo so you've written in but now you might be saying ah look that's more verbose i had to write two more characters in a space true all the other examples will be increasingly in the other direction let's now instead of an int pass a string and in this case capital s string is just a noisy of stood string that's all it is so the current way i would write this is i would overload on construff and r value reference and in the first case i would copy from s and then the second one i would copy from stood move of x that's what we teach people and now we'll compare that to the new way of saying just in string s so let's take a look at that example so here we have old in which is the overload set i've got new in and the way i've been testing these is to say okay i've got here's where i call my run history function where i'm just going to run the history of two things the old thing and the new thing and then print their histories and compare them side by side and so what i'm going to do is for three different cases starting with a non-trivial l value so look there it is there's an l value x it's a named variable that's a an l value i'm going to do the same call old in in express the current way and new in the new way with the same argument x and see what they do then i'm going to do it with a stood move of x and then finally with a real fully pure r value a real temporary temporary string on the right hand side you'll see that for a non-trivial l value we in fact are doing what we expect we're writing the copy constructor in both doing the copy in both cases because we pass the string by value it's a name string so we're going to copy it into the the copy from function but for the other two you'll notice that we correctly do a move in both cases so what this means is that in both cases including in the in string case we see oh this is an r value argument both of these are our values that means at this definite last use we're going to cop we're going to move rather instead of copy but i didn't have to write an overload to say that i didn't have to write stood move anywhere i just wrote a function which now i can take the address of because it's on an overload set i just wrote a function that says oh i haven't want an in string where if i copy it and you pass me an r value i'll just naturally move from it because that's what we've already learned is the right thing to do is what we teach people to do and so on the right you can see that that's in fact what this implementation does so that's demo number two and you'll notice that i'm putting bolt links on each of these so you can see and try each of these yourself and try variations but now let's do something a little harder two in parameters well two parameters it doesn't seem very hard but if we follow the advice in this case we take two in strings and we do what we tell people to do today if you copy from it you consider overloading for r values well then what's going to end up happening is that you write this combinatorial in this case four set of overloads one for string const graph constraint once for r value constraint once for construct r value and once for our value r value instead i would like to be able to just write i want two in strings please please do the right thing sir so this example looks like this and again the goblet link is there so here's the overload set we write today here's what i would like to write instead and here's what andrew sutton's prototype compiler does again i'm doing the same compare function just to get the histories of two calls and i'm going to do two l values l value and r value our value and l value and our value and r value all the combinations and old in does exactly what we think it does copy copy copy move move copy move move the nice thing is when you look at these let me try to use a different there we go when you look at these so does new in but all i had to do was write in string in string and when i copy from them in the body it automatically does the copy copy for two l values copy move for l value r value move move for two r values at these definite last uses of s1 and s2 now it's more than just that it's simpler to write this code the fact that i'm writing all these overloads actually generates bigger binaries bigger object code and you can look at yourself and on godbolt and i was going to scroll through and show it to you you can do that yourself instead i took a screenshot and here is the actual assembly generated on godbolt for this example the larger piece of code here if you zoom in you might be able to see it or it might be pixelated in the slides but you can see it yourself online is for these four overloads it's about 250 lines and for this function which does the same thing it's 120. so this is kind of nice because you remember that we already said we get the same optimization move from our values in any combination so they're equal on performance at runtime they're new in wins on being easier to write for programmers so on simplicity and it wins on executable size on the object file size try more examples yourself and see for yourself how the object code varies but to me this is a win-win-win because it's just as fast way simpler to write and gives me smaller object files which usually we like now you might say how often do people do this in fact i wondered how often do people really for two in parameters do this construff ruff-ruff ref ref construct ref ref ruff-ruff construct overloading so i asked twitter a few days ago i asked have you ever and so this is going to overcount it's going to because it's going to count anybody who's ever done it once in their careers but i was curious because i was thinking the answer might be like one out of ten have ever written overloads like this to optimize for our value arguments i mean i know standard library implementers do this but for my twitter followers and the people they forwarded to have you ever done this asking for a friend and for this talk i was kind of surprised that 25 that to me that was high of people who've done that but in the comments that were that followed i i found some interesting information as well so just a few highlights one of them was don't remind me i've done it with four arguments and we know what two to the fourth looks like and other someone else said assuming x isn't templated i that's right because you can't actually do it this simply if x isn't the template it's harder as we already saw this is the easy version today assuming x isn't templated yeah i've had to do that i used a macro so this is an example of what complexity forces people to do instead another example of what people do instead is they say i'm not going to do that at all i'm just going to bail and use perfect forwarding which means writing a template it's less clear because perfect forwarding is an expert level feature and it's changing the problem because perfect forwarding doesn't express in this isn't actually saying the same thing anymore but macros and perfect forwarding is what this drives people toward even for when it's just two parameters or it drives people to quit c plus plus maybe not this specific thing but this being the last straw on the camel's back before they just break away from c plus however i have to say my very favorite answer which really surprised me was this one thank you marcelo i'm not even going to try to show you what this looks like with three in parameters of concrete types just press ctrl c ctrl v a few times make sure your rights to move in all the right places i had even for the two parameters i had to triple check my code to make sure i was writing it correctly instead i would just like to tack on the third in string parameter thank you very much and not have to overload but now let's look at templates let's go back to a simpler version of the example with just one in parameter but of a templated type turns out you have to write this nest of things basically you're saying if i should pass by value so i should pass by value if it's trivially copyable and the size is less than something let's just say you can make your own predicate here if i should pass by value so i'm going to use where c plus 20 requires or if you don't have that use enable if to use this overloaded template which passes by value great otherwise if i shouldn't pass by value i'll pass by constraint great and here's the fun one remember overloading for r values and especially in templates you may want to do that because i'm going to copy and t could very easily be cheaper to move than to copy so i really am incentivized to always write this one for templates the copy and in parameter i then additionally write this incantation that niko yosudas taught me and it happens to be the right thing here to turn this into a move and i still write forward instead of move but we'll call this close enough instead i would like to just write in auto t now let me for a moment defend this because one of the first things you're going to say is hey shouldn't this be have at least one extra line template type name t in tt yeah that works too it's still way better but i can actually use auto here where i can't in today's guidance so today this auto this it was just c plus 20 for a an implicit template parameter i could write this here it turns out that in fact i didn't know how exactly how to write it so i asked the world's experts so thank you again to villa votilaiden and to andrew sutton for over the course of several emails teaching me and learning how to write this using auto instead of template type name t it you do not just change angle t to angle decal type of little t that that is not correct and it's still more verbose so i think it's a fair comparison to say no i'm going to show this today's guidance with template type name t and i'm going to show this one with the natural way you could write it in c plus study because now it is natural to write and it is feasible to write with this new proposed in qualifier but if you still aren't convinced fine i'll take the comparison with this any day of the week and it still wins hands down we're going to again compare current with proposed we're going to do a trivial l value a non-trivial l value non-trivial r values of two flavors to make sure we move from them and again we see no history instrumentation for the int because i can't instrument an ins and keep it trivial but if you look at the cogen as we saw already it's the same passing in by value otherwise i copy from the l value and i move from the two flavors of our value cases but all i had to write was this not this i'm not going to demo how to do a templated version with say three parameters you can go and ahead and try it we know how to do it but cut and paste is your friend and make sure that you tweak everything correctly and i don't think anybody will complain it's maintainable but if i wanted to do that for this new style i would just say in auto in auto in auto and it would work in fact let's do not three parameters but six just cuz this will be our last demo and i'm not going to show today's way of doing it i'm just going to show here is a template with six generic parameters and i want to pass trivial ones by value the cheap to copy ones by value otherwise by effectively const reference and also effectively overload for but it's not really an overload here to move from our values and i'm going to put a few line breaks in the history just to make it easier to read and i'm going to copy from each of these variables i'm just going to group them just for yucks and now i've got an int a string and various strings and now we're going to have this call site new in we're going to pass an into string move s2 s3 42 and then a string temporary so the first thing we're going to do is as we pass these all by in is we're going to copy from a and b so first we see the default constructor outside the call that's creating this string temporary at the call site then we get inside the function and first thing we do is we execute copy from a comma b a and b in this case are i and s and int so we should see nothing in the history for that because we pass that by value and it's not instrumented and we should see uh s is a an l value so we should copy from that so we should see a copy and sure enough we do we see the in the copy from call we see the copy constructor and then the destructor of that object and that's in as we copy from b all right the next thing we do is we copy from c now let's see here in this case c is an x value it's an r value that's a move from l value i'm going to say or a stood move of an l value so this should say what it should say move as we copy from that particular c we should move from that because that's what the caller said and in fact that's what we see happen we have the move constructor done for c finally we're going to copy from all the others in one shot d e and f are a string that there's an l value so we should copy that one and in 42 which we just passed by value and there's no instrumentation and then a pure r value a real temporary object of a type string which we should move so we should see copy nothing move and that's exactly what we see so there's an example of in parameters and you can also try out we're still in the process of building the other kinds in out out moving forward they're in various stages of construction but hopefully that gives you a sense of what this is like and you can try all these online so we saw that about 23 of the measured guidance was passing parameters but another seven percent was about initialization and this is actually i believe directly related because of out parameters because out parameters reach back to the caller and set a value now today what do we teach we generally just bail in in c plus including in the core guidelines and say initialize at the point you declare a variable and that's fine most of the time if you have a sensible value then if you don't yet have a sensible value you have to put in a dummy value and because that's expensive for big pods and arrays we always tell people oh you know that thing we said about always initialize at declaration yeah except you know you don't do that for arrays for pods for stud array for example because that will just generate dummy rights that it turns out optimizers have a hard time getting rid of when you later put in program meaningful values putting in dummy values in these cases we already teach not to do that because they're not useful because we're going to overwrite them before we hopefully read from them they're expensive because compilers can't get rid of them very easily despite many years of trying and they're error-prone because if you have undefined behavior tools that check that you initialize your variables it will mask the bug because you're actually not initializing your variable when you give it a dummy value at declaration you're not giving it a program meaningful value and now the tool can't tell that well that wasn't a real value that you shouldn't be trying to read back from instead the holy grail is a visualize before you use a variable and for a local that just means that if you declare it and it's not yet initialized like an int on the stack that you assign to it before you read from it that's all and ada c sharp they do this millions of programmers live with these rules and they works for them and it finds bugs today that we're not finding in c-plus boss now earlier on i i said today and we can't really distinguish between in out and out only parameters because there's no such thing as an out only parameter expressible in c plus plus and that's true with one little exception this object in the constructor is effectively an out because the constructor takes a raw buffer of memory and turns it into a constructed object that is out so let's revisit the definition of out and we're going to make one little tweak instead of just saying any non-const l value we'll say that or an uninitialized object when you remember on every definite first use you have to assign to it if x is not initialized which we are told by the call site then that becomes a constructor which basically means spoiler alert every function that has an out parameter is in effect a constructor a named constructor when you pass it an uninitialized object so today we teach stood array of byte which could be hugely big by the way and this is not initialized today that's what the standard says and you want it to be that way then you call it in the loop to get next chunk and that may or may not fill it we we hope it does and we test for that then we process the data but get next chunk today maybe just take an array by reference we don't enforce in the language not to read from x's contents before writing to them we don't enforce that we write to it now we do those things and we test for them but the language doesn't say hey if it compiles you did those things instead the proposed equivalent is that i'd be able to say out on a get next chunk style api which enforces i don't read from the value before which knows whether i'm passing in an initialized variable or not and if it's if i write to it i will construct it i'll show you a specific example in a moment because for a ray of bite it's just a pod so it's just a trivially copyable type let's say trivially assignable cell constructor has a slightly less interesting meaning but i will guarantee that i write to it including initialize it the first time and that i won't read from it before i write and this should be the same if it's an array of byte of four not just a ray of byte of a million it should be the same for array byte four as for int which is the same size on most platforms and in this proposal all types big pods arrays ins have all these same rules now for types today that are initialized of declaration like say a vector event today we call the default constructor that may not do a whole lot for vector but it's an example of these dummy writes because we're now going to get value data that's going to fill the data but if we could just construct it on the first call to get value to fill the value into data then we could eliminate some dead writes already from that vector event so the way i'm proposing to opt in to say no i want to just allocate enough storage for a vector of in but not construct it yet the same as if i wrote into data there or byte data to write equals uninitialized and you'll remember on the previous slides i put in in in comments as if equivalently writing equals uninitialized but there it's already implicit in the language this would make it consistent throughout the language and i would enforce that i don't read from the existing value of v which is the first time through it's not constructed yet so that's good and then when i set it if v is not already constructed i will turn that into a constructor call if it was already constructed it will be an assignment and then i will make sure i do that before i read from it this allows you flexibility for the last example let's say it's some other type like database info and i might want to construct it two different ways i can't easily say that in c-pluses today i can write a lambda that does this and then kind of tries to move the result back but i can't write alternative constructors easily today but here i can i just declare it as uninitialized give me enough space on the stack for a db info and if the main site is there call one constructor it's just a function with an out parameter is a constructor otherwise call some other constructor which in this case just has a different argument but could be a completely different parameter list with 100 parameters if you wanted to and it would just work so here is the entire guidance to an implementer this is the implementer compiler writers cheat sheet for what they would have to do this is in much more detail than we actually teach have to teach programmers programmers is just declare the intent do i want an x i could read from in when i can read or write in out that i assign to out that i move from move and i pass along forward i would like to have that be in some future c plus maybe five or ten years from now that that's all i have to do to teach parameter passing in c plus plus or any equivalent language of equivalent power so empirically we've seen that parameter passing and initialization are about 23 at least so far in the guidance i've cataloged and another 13 is in the kind of class you author am i writing a proxy am i writing a com class am i writing a value type am i writing something else am i writing a virtual interface or a base class with this proposal i talked about today which is numbered 708 when it gets published and the meta classes proposal which is numbered 707 having actually looked at the rules and analyzed and cataloged and personally read the literature for months i believe that about 30 of what we teach people about c plus was today we could stop teaching if we could have those features and then a mode that says don't use the old thing because as long as the old thing is around you still have to teach that but for new code that we could stop teaching about thirty percent of what we currently in fact teach empirically about c plus plus if we had intention based parameter passing initialization and meta classes so what i've tried to do is contribute an empirical attempt to catalog classify count what we teach in the complexity so we can measure the complexity of c plus also not just say it's complex but to be even more precise as to how much more 90 like bianna said and go well beyond that into exactly where are those sources and we've talked about how to address two or three of the larger categories two in particular in this talk that add up to a potential 30 reduction if you include meta classes in the other talk you could read more at my github repo h stutter 708 that's going to be the paper number when it's published and it has some examples and test cases you can go to cppx.org and find out and try examples of your own there not all of them will work yet but many of them do by the way one last teaser answers are in the paper what would an out this mean hmm well every out parameter can both assign a value but also construct an uninitialized object hmm what would operator equal taking in x mean well n means an x i can read from and it if you copy it knows to copy from l values and automatically moves from r values so what would writing both mean think about it and compare your answer to the paper finally let me summarize many of the cpp contacts i've given over these last seven years since i started a systematic effort to look at what are the sources of c plus losses complexity and how can we simplify c plus plus this is talk seven in that series i talked about starting this is in roughly chronological order i'm going to skip the c false's core guidelines which is about how to use c sources in a simpler way today today's c plus in a simpler way the lifetime proposal and the paper number is 1179 is about simplifying by directly supporting owners and pointers and eliminate classes of errors like use after free use after you invalidate an iterator to know those things and give you compile time warnings and errors to not make those mistakes those have been prototyped and implemented largely and next steps there is continue the upstreaming in clang which has just begun another part of this effort is simplifying comparisons to directly express the comparison intent to get rid of boilerplate and errors that has been adopted into c plus plus 20 already so the next steps there is for implementers to implement it metaclasses itself relies on reflection const compel time programming consti val programming and code injection once you have those metaclasses themselves become a very thin veneer that is moving along well in fact reflection is advancing well in the committee and it is one of the very small the handful of priorities six or seven priorities that the committee has formally adopted to give priority to working on in the next three years so that's moving well and in fact c plus plus 20 const eval that feature came directly from the metaclass's prototype implementation and anderson thank you again so it we're making progress it's all coming into the standard and we're on track static exception handling i started talking about two years ago it is not yet prototyped we got initial feedback from the committee saying this could be a direction that we're interested in exploring please answer these hard questions which we're going to do and let's build a prototype and let's actually verify you can get these benefits and then it takes a language extension if it does so the next step is to say great we've now seen there's enough interest to justify doing a prototype so we'll do that next and then today i talked about directly expressing so and i should say by the way for why static exception handling that simplification because the greatest fracture point in c plus today is the huge rift between libraries and code that and projects that report errors using exceptions and those that disable exceptions this creates a rift at a fracture point in inconsistencies that i talked about a year or two ago here at this conference so check this out and you can see the more in paper 709 and finally parameter passing directly express intent again like all of these simplify the way c plus s is actually used by directly expressing intent to get rid of this case boilerplate and unify initialization we are currently part way through prototyping that in clang all the prototypes are available at cppxgodbolt.org so the next steps there is to continue working on that now before the pandemic came i intended to bring this paper to the committee probably at this next upcoming meeting which would have been new york two months from now but that's been canceled we're not meeting face-to-face i'm not going to try to bring it right now because the committee's bandwidth is reduced we don't have our face-to-face meetings we're still making some progress but the committee needs to focus for now just on those six or seven priorities for this sequel 23 cycle not all of which will land in c plus 23 even without the pandemic but finishing like the co-routine uh enabling the standard library a module enabling the standard library to finish c plus 20 reflection pattern matching this is not the time to bring a brand new big proposal to the committee so i'm going to publish it on github which i've done you can find it today it will be a committee paper but when the committee has more time again after this pandemic is over and we can have a more normal life then we'll also be able to make use of what we learned from the prototypes and any feedback that you may have so please open issues against that repo last thought c process has always been about efficient abstraction and i want to emphasize in that order too many languages design a great abstraction well-designed abstraction even and then try to make it efficient that's what made small talk slow with all its messages it was elegant but you couldn't make it fast compared to c plus plus that's what made c plus or so x concepts fail because it incurred overheads and then couldn't optimize them away instead learn from what we already do so i hope with all of the examples i just mentioned in the previous slide lifetime how we use owners owner types and iterators our pointer like types are already being used widely meta classes we already have guidance on how to write certain kinds of types parameter passing we have rich guidance on how to pass parameters learn from what we've already done and we've already learned the efficient way to do those things but by hand and then for the important ones of those abstractions we know the efficient way then make the abstraction build it into the standard library or even the language as appropriate so the programmer can directly express the intent and instead of writing it by hand it's automated this describes what i try to do with meta classes it describes exactly what we talked about today with parameter passing and by value exception handling express intent and then implement it in an efficient way welcome back so i've been looking at your questions and but first of all let me say the same thing as john and thank you john for helping us put on this conference without you this would not have been possible and with all of our supporters including all the volunteers a personal thank you for me and from the standard c fossils foundation who puts this on despite everything we were able to have cppcon this year in such a great way so i really appreciate that going to the questions i'm going to take them mostly in order from the upvoted ones so please feel free to hit up vote if you haven't already and the first question actually the first two are very similar wouldn't abi stability become even harder if an in parameter could change from pass by value to pass by reference at some point because of some small change the answer is yes that could be and so today you would be changing your pass by value to pass by reference manually so you can see that but this actually overlaps with the next question which is how would i tell the compiler that my type is cheap to copy or tell that i really want in parameters of it to be by value i think that both of these which i have not yet written in the paper but which is on my to-do list i think both of these can be addressed the same way and that is by how giving the type away to opt-in to how it would like to be passed and you probably wanted by default to enable the type author to do that i can imagine cases where you may want the owner of a system to be able to up that to make the choice one way to do that would simply be to have a trait which defaults in certain ways so you might in fact if you write it as a trait then we can simply provide the default uh the condition for should pass by value and then you can specialize it for your types of course anytime you hear traits i say that mostly for familiarity remember that these days we would normally spell those instead as constants for functions and overloads that kind of thing so those are ways that yes i think there if there is a way to opt-in then not only can it make it easy to say hey here i want my type to be passed by value or not but it can help address abi stability as well while still giving you that automatic optimization for all the many places that use your site if i have something where i can say it optionally once per type that's a great place to be the next question is how will the parameter description work with inheritance what if the base abstract method defines an in-out and the indentation does not write to the parameter so this was actually this is a very good example this was touched on in the talk so first of all they have to be consistent you can't say take an in-out parameter and a base virtual function and override it with an out so that they have to match the declarations have to match otherwise you're not overwriting the virtual function but if you recall in the talk or if you go back in the slides one of the things you'll see is that it says for for those for in-out the rule is if it's not a virtual function and you didn't write to it on any path then flag that because you wrote in out if you didn't won't ever write to it on any path then you meant in you should have written that but we specifically have car that uh that exception out if it's not a virtual function because the way that that i think is the right way to think of a virtual function is that the virtual function is its base version and all derived versions together is the function and of course that's an open set because unless you deliberately prevent people from further expanding and extending that can include functions in the future that aren't even written today if i can only see part of that set i can't verify in out so by saying in out it could be quite reasonable in a base virtual function to happen to have the default implementation not right to the parameter and use the out but by writing in out it leaves the option for derived overrides to be able to do that so we are declaring the intent and exactly what is allowed but because we can't see the whole body we're not going to flag hey you know you never wrote to this at this in-app parameter so why did you include the word out well you might have we just can't see the whole function because conceptually the whole function is all the overloads that are that work together the next question is do you have a conservative estimation of the time required for the language to evolve in this direction given the constraint of language teacher backwards compatibility or is this yet another way well there's a few things in here any standards proposal of this kind is going to take years so i i've been working on this and getting feedback as you'll see acknowledged in the paper from a lot of people already and this is actually i first started writing up about five years ago it is now at the point where i feel safe talking publicly about it because i was going to bring the paper to begin the standardization process but we're still at the point where the prototype is is being implemented it's pretty complete for in but we're still working on things like variatics and things like that and virtual functions so this is going to take some years and in the talk i said i hope that in the next five or ten years i'll be able to teach just this so i understand that that requires more patience than many have that's the the only way to work in the standards world is to have patience and be designing things that as you would like them to be a few years from now having said that this is something the other part of the question is a good one too which is is this adding complexity to the language absolutely it is so i bullet a simplification just like i have with some of my other proposals which it is but that's if you don't use the old thing anymore and there's a legitimate objection that says well but for the foreseeable future old thing code is going to exist so i will have to still teach that and learn that yes but so there's two answers to that first if we get a simplification like this that subsumes and is a replacement for an old thing just like the using alias completely uh subsumed all the uses of type deaths and we can ignore type tests and use only using in the future that kind of thing but more so then at least for new code we can teach people to only use the new thing if you have a c plus loss whatever compiler use only the new thing in new code and then the code that you're writing is simpler and we can actually provide compiler modes and static analysis checker modes that will warn you if you program outside that subset of the new language which is smaller but that's my convention i hope to have all of these things add up to a place where there's enough critical mass where we can start having a serious conversation about do we now have enough to subset the language now be very careful with that because subset does not mean it implicitly means answering the question are you creating a fracture of the community and nobody wants to do that but if you recall beyond this talk on monday one of the points that he made especially about the core guidelines in gsl was a super a subset of a super set if we see what's missing in today's c plus plus like gsl said span was missing which has now been standardized for bound safe access to arrays okay we add a few things then when we have the union of things that has all the things we want including safety and simplicity and performance then we can have the conversation about whether to subset and say well now if you look at all the new things and for the parts of the language that they are total replacements for what about having a mode where in my cpp next file or something i only program with the new things so that's a conversation we can begin to have perhaps in the next few years in the meantime yes we're adding and making the language say 110 more complex instead of a hundred percent you're adding ten percent but at least in new code i'll be able to more to use the simpler language and maybe someday we can actually say we have enough of these general things but we can actually start saying what would it look like to have a world where i program only in the new mode the next question is what about when out is optional so we have a way of saying that if there is such a thing as optional now the standard but if we want to say something in the language um so titus winters calls that maybe out that's actually discussed in the paper so please look for the string maybe out maybe underscore out i think it is in the paper and i believe i put in discussion of that but basically that's okay you can say that within out because the rule is as long as there's some path that you write to that's sufficient for in out it's for you to satisfy that you really didn't mean an in parameter because you could do an out operation but not every path is required to do that and if you want to say something stronger of the form like out of optional you can actually say that directly because you can use the type if you want if that's the semantics you want to have next question does that mean retiring or deprecating single ref double ref construct syntax or will it add to just an already fat standard well of course it would add to an already fat standard yes but this is like my answer before once we have this so one of the things i don't remember whether i say in the paper but i'll go out and say it right now i personally from what i've seen so far in the last five years working on this proposal and in conversations with others and looking at the implementation i think this is a complete replacement for today's how way of describing parameter passing that you can use only this new way in in out out moving forward and express everything just as efficiently as today and much more simply in the smaller object code so it's a complete replacement and then remember that the only reason that we added references in the standard in in the language in the first place aspiana was for parameter passing i believe i mentioned this in the 708 document i definitely mentioned this in my blog post in from february of this year february 2020 look for references comma simply where i make this point in uh hopefully fairly blunt uh detail so yes actually i think that that references should only be used largely for parameter passing we shouldn't be specializing templates on reference types for sure that's just awful as for the reasons i give in the paper and since with this new style of parameter passing we don't need references yes i do believe that this is a path where we don't need references at all in c plus plus that's controversial so go ahead and start sending the the hate mail and the angry pitchforks my way i'm ready for them but this is the kind of thing we have to think about if we are really going to be serious about simplifying c plus loss and not just moan about it every year on reddit and not just talk about it and then whoa how bad things are if we are going to be serious about simplifying c-class plus we should be looking for abstractions that directly express the intent of things we already do bake them the important things into the language so that they're automated instead of ad hoc and that as a result make other parts of c plus plus no longer needed and then we can have a discussion about having a subset that's as bjorn has said really is about ten percent the size of today's c plus plus and yes this is intentional it's why i've been working on these things in this way for the last five years what happens with unused parameters for example in an abstract based class i'm not sure exactly what you mean but unused parameters should work the same way if you if you declare a parameter and then parameter and don't read from it for example that's fine perhaps that's the kind of thing you have in mind of course if you declare an in-out parameter and don't write to it on any path then you would get an error and you may need to suppress that in order to say no i really didn't intend that which i think is a fair thing to do i think it's fine for people to be able to write something like attribute suppress this error to say no i really didn't mean it and deliberately opt out of a language rule or a static analyzer rule that's why the the c plus core guidelines do that in the gsl is we have the suppress for no i really mean to do this that way you can express anything you want and you can go outside the guardrails if you need to but now you can grab your code for the places you said trust me when there is a problem later and you can have a better time finding out okay here are the places i told the language not to help me and therefore those are the places i'll look first let's take one more question let's see i'll take this one with the uninitialized approach does the assignment now get all the problems of initialization think about the chaos of initializing a vector i think so so we'll have to see with with a usage case use cases but i believe by taking the definite assignment rules that we already have in ada and c-sharp in other languages where we've shown they work applying those to c plus plus and especially you need out parameters to do that you can't do it easily today you need out parameters so that you can then delegate construction to a callee the classic example why you need out parameters if anybody tells you you don't say how do you write get next chunk there's your your poster child example then yes you'll be able to address all the initialization issues i know of because you will be able to actually require in it before use you must construct an object before or right to say an end before you read from it and by saying you can do that separately from the declaration for local variables it lets you also say you can wait until you have a program meaningful value which most of the time you have at the time you declare the variable but sometimes you don't like get next chunk or filler a and for those cases which are common when you call c libraries for example and for those cases you will now be able to still get solid guarantees of initialization in it before use even when you're using those kinds of apis so thank you very much again for coming to this talk to cppcon in general it please stay here for a few more minutes and listen to the band or go to the set the session that's going to be taking place on zoom now for looking at cppcon 2021 to give any feedback you have about this week and if you are interested in being part of planning or maybe helping or at least being a fly on the wall for next year's event thank you again for coming right here we'll continue with the band safe travels back home which for many of you will be to your kitchens or bedrooms in your same house and may we all be safe until we meet again thank you you
Info
Channel: CppCon
Views: 42,342
Rating: undefined out of 5
Keywords: c++ talk, c++ talk video, cpp talk, cpp talk video, c++, cpp, cppcon, c++con, cpp con, c++ con, cppcon 2020, c++ tutorial, c++ workshop, programming, coding, software, software development, teaching c++, passing parameters in c++, initialization c++, initialization cpp, abstraction c++, abstraction cpp, making cpp easier, making c++ easier, herb sutter, herb sutter c++, herb sutter cppcon, herb sutter 2020, herb sutter youtube, future of c++, C++ is complex, simplifying c++
Id: 6lurOCdaj0Y
Channel Id: undefined
Length: 81min 23sec (4883 seconds)
Published: Sat Oct 10 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.