So I said, okay.
I'm going to tell you a little bit about C++. And most such talks either about what language is or how you use it.
This I'm trying to make a talk about how the language became to be what it is and
is the key evolution from the early days up till about three years from now.
And if I get a bit boring, you can look at the pictures.
Essentially all of the pictures have something or other to do with C++.
Like, what do you think? Those turbines have been programmed in and so that's it.
I am going to go a little bit into what is C++, his role in the world.
What is what did I intended to be and what what what is it now?
Then I'm going to give a code example. I really feel like a total fraud if I talk about programming and software development without showing code.
I mean, if you see a presentation about software development without code, I start to worry and then I'm going to talk about the reason evolution.
A lot of the talk has to do with what has happened in the last, uh, minus ten plus three years, something like that.
And my, my thesis here is that the value of programming language is the quality of the applications.
What matters is what interesting things you do with it.
That is my measure of success, not the how clever code I can fit into it.
You were column published format this this is this is very much a practical exercise trying to to do something good in the world.
Of course, you don't control what people are using the language for and some of the things you might not like.
But these are the things I consider somewhat cool.
And I am not going to enter into language wars.
I am I try not to be rude about C++ applications.
So that said, you are not going to drag me into that and there's lots of interesting stuff here.
So what I've been doing since my PhD days is distributed systems and I'm still very interested in that doing it.
There is my one of my notions of a distributed system.
It's a distributed system with wheels and a lot of C++ turns up in places where
you would never think about it and you will never see it if it works right.
It's if you notice, it's C++ is probably because something went wrong.
The point here is that nobody understands all of this.
Nobody can understand in any depth all the applications that I was just flicking through a few pictures of, neither do I.
However, the purpose of the exercise, as far as I'm concerned, is to help people that are building these things.
Therefore, if I build something that can only do what I can imagine, I failed.
You have to do things I couldn't possibly imagine. The group here has more ideas, more needs than I could imagine, and that's part of the point.
So what actually matters? The answer is lots of things.
And one theme here is that we need stability and evolution.
We need a language to evolve, our toolset to evolve so that it can handle new things.
The world is changing. We're changing, the challenges are changing, and the language has to do it.
On the other hand, you've always seen languages that are really cool for about five years.
Then their design gets a promotion and it dies. We can't have that, not for things that lasts for decades.
A lot of the things in my pictures have the interesting property that they were written ten, 15, 20 years ago.
They are still being developed and changed. You have to handle that span.
That's really hard and obviously there's enough in this kind of stuff to talk for days.
I have one hour. I'd like to point out that the best being the best at one or two things is not sufficient.
I mean, that's how you can write a really nice paper. I'm nothing against academic papers.
I read a lot of them. I have written a fair number of them, but that is not the end product for tool.
Building a tool is good enough if it is good enough for everything that somebody's using it.
Needs. Now you have to remember that no language is good enough for everybody and for everything.
But if you should use a chore, it should be good enough.
At what? At every aspect of what you are doing, not just being the best at something.
And so let's go back and see what the world was like when when I started photography was mostly black and white.
Seems that is a large computer.
It's a PDP 1170. It allows a programmer to have 250 K of memory and it runs with only almost a megahertz.
Only almost. And this is Dennis Ritchie and Ken Thompson working on it.
Notice the highly advanced IO system. That was what the world looked like.
And there's lots of things we didn't have function prototypes.
I hadn't invented them yet, so I didn't have it. And it was the state of the art in aesthetic development.
Yes. Lots of languages has functions, document checking and conversion, but C did this all kinds of stuff.
PDP levels were cool. 90/100. They didn't even have one.
That's a teletype. One of the points is that everybody knew that object oriented was useless.
This is almost right because 99% of people didn't know what object oriented was,
never heard of it, and of the ones that knew about it, knew it wouldn't work.
It was too slow to spatial purpose and too difficult for ordinary mortals to use.
And I tried to convince somebody and says, If you want a virtual function, you haven't done your analysis right.
I mean, you want to call a function. You don't know which one it is.
It's absurd. So there were some obstacles to overcome.
I point this out because in retrospect, a lot of this looks trivial and easy, so I probably won't convince you, but it wasn't easy.
So here's sort of a history chart as it relates to C++.
Here is a line of development where the purpose of the exercise is to extract every single byte.
Every single cycle out of the machine starts with a simpler machine code, go through BGP on C and then to C++.
And up here we have the great improvement in programming, the greatest in history,
which is basically somebody figured out that we should have human oriented things, application specific.
Concepts in a language so that we can talk about our programs in the vocabulary we use when we design things,
as opposed to looking at the machine all the time. That's Fortran.
And as soon as people had Fortran business people wanted one.
They got COBOL and everybody wanted one.
And very soon we had about 20 of them and had the net effect that everybody could write in a specific domain, much more pleasant than assembler.
However, they couldn't talk to each other. The terminology was different.
The data formats were different. They couldn't even exchange data.
So Simula here came about together with object oriented programming as an attempt to say, Why put application specific?
Concept into a programming language.
Why don't we instead give the programmers the ability to design their own abstractions, their own concepts, their own types?
And that's how we got object oriented programming.
And if you write in any programming language that calls a Type A class, you can say thanks to a question.
You go there because that's where it came from. Computer science was very new.
He was trained as a mathematician. He knew what classes was.
He did not know what types were. And so I needed something that could handle abstraction and could handle hardware.
And that's why I built C++ by allowing abstraction mechanisms to be used there.
And lots of interesting things happened after that.
Now, C++ is, as far as I'm concerned there, so that I don't have to choose between elegance and efficiency.
When I do things well, they are elegant and efficient.
That is when you express things really well, really clear, really logically consistent.
Hopefully the optimiser goes and generates a really good code.
That's the idea. And sometimes we get it. Don't get it all the time and we can do even better.
But that's the idea. And we do that by defining lightweight abstractions, not big, heavy, complicated abstractions.
They are relatively easy, and you can do them in any language.
But if you want a point and a matrix and a complex number, it gets really quite difficult.
And that's where the challenges are. And so she has been developed as language for resource constrained applications.
There's lots of applications that you saw on those pictures and lots of the stuff that I worked on.
Well, starting in the eighties and still today,
where you could do much better if you had twice as much memory or twice as many processors or twice as fast processors.
But you don't. Those server farms cost 60 million USD, and if your code is half the speed of what it should be.
You need to buy two and you have to power them up and run them and maintain them and all of this kind of stuff.
So this is where resource constraints matters, and that means C++ is deep,
deep in our software infrastructure because that's where you have the constraints of performance and reliability and all the other good stuff.
And C++ offers a direct map to hardware and a zero warhead abstraction.
Those are those two lines on the history chart. And again, no language is perfect for everything and everybody.
And I don't know how many of you have have read the Dragon book.
It's a classical textbook in about how to build compilers.
It shows the knight armed with the weapons of computer science, defeating the dragon of complexity.
Sometimes the dragon wins. We haven't reached perfection.
We can do much better. So here's what I mean by a direct map to hardware.
The primitive operations map to instructions on the set.
If you add two integers, it's the integer edge operation.
Seems simple, but a lot of languages don't do it. Memory is just a sequence of objects.
You quite often bytes and you have addresses that can show which by the which object you are talking about.
That's it. It's a brilliantly simple abstraction that any stretch you made you can compose object the simple concatenation.
Like if you take some of the same type and put them next to each other, you get an array.
If you put things that are different types together, you can get structs and classes and things like that.
And if you need to refer to something that's elsewhere, you have pointers that are simply, simply machine addresses and sweet and sour sauce.
So basically, this is the real secret of C in C++.
It's really simple. It's really easy to map to the hardware.
It's compact. It's efficient. Okay, so down by the hardware,
life is actually rather unpleasant because there's not much help and you don't really want to work with bytes and and words and such all the time and,
and raw pointers and such. So we want to abstract from it.
And so the basic idea of C++ is that it should allow you to build your own types, and they should follow what I call the zero or head principle.
What you don't use, you don't pay people and what you do use.
You shouldn't be able to encode any better.
So if I'm providing a notion of a class, you should not be able to hand code it with pointers and structs and stuff like that does anything better.
And there's lots of examples here. And finally, sometimes we don't actually need to generate any code.
We just compute the answer at compile time. That's getting more and more popular.
So here it's abstractions all the way down. We start with our high level abstractions and they build on low level abstractions.
They build on the language which builds on the on the basic machine model.
And the machine model is also an abstraction. Of course, there is much more to the machine architecture than that.
That's caches and all kinds of stuff like that.
This is an abstraction. This is Dennis's abstraction. It's a good one.
I borrowed it. And you go down, you get to the hardware.
And what do you find? No. An entire machine does not execute 86 instructions directly.
It translated six instructions into a much nicer instruction set, which it can optimise and execute better.
It's abstractions all the way down into turtles, and you always have to abstract from concrete examples.
There are people who think abstraction is another word for bloat.
This is not the case. If you do it right, you abstract from concrete examples, maintaining performance all the way up.
And you have to keep simple things simple. Because sometimes when you abstract things so that it can do everything, you can do nothing.
Simply you want simple things to be simple. These are sort of design principles that I've worked with over the years.
And then there's this question of naming How did C++ get to be core C++?
Well, there wasn't a language here called CPU. It initially stood for Cambridge programming language,
then they ran out of money and combined with Imperial and then was combined programming language.
And then it was too complicated. They couldn't build it and it died, except they built a simple thing.
And Richards built a similar thing called Basic Spiel we had at M.I.T. actually.
And then it became B for a short while. And C was Dennis's work that made it efficient and better for poor hardware use.
And then she ran classes, as it was called, for about three years till I was told I couldn't call it see the classes because
some people were calling C old C and that was supposed to be rude to Dennis.
I was not rude to Danish. I had lunch with him most days and never set up.
We never had a hash word between us and then I tried to call it c,
c c 84 that never flew because the people from the C committee came and said, Well, please don't do that, John.
It would really be embarrassing if a superset or C 85, the standard C would be a a a subset of C 85.
Anyway, they didn't finish till 89, but anyway, that was not so.
I had a competition for calling it. Something and C++ one.
As I said, we knew plus plus C was semantically better, but that was too much of a joke.
So. What is straight you doing up there?
The answer was he was the main designer of Kpl and it didn't matter Willow's Cambridge or combined because everybody knew it stood for Christopher.
So that's. You still got it there? Uh oh.
I should point out that's Maryhill Hill, where I worked and where I designed C++ right over there.
And that's Cambridge part of it. So what features do C++ offer?
Well, we had a competition a couple of years ago for what is your favourite C++ feature?
And when Roger suggests that in Curly, we all backed off, that that can't be beat.
That's it. That's where all the magic happens. So one of the things that distinguishes C++ over the years is this model.
You make objects with constructors. And if you don't say anything else in a scope and the end of the scope,
the destructor fires doing the magic, cleaning up the messes, closing up what should be closed up.
That that's the really key. And I looked at my notes and it's a real call, C++.
It came in in the first two weeks of development back in 79, together with classes,
member functions, information, hiding function declarations and other stuff like that.
And basically, that is the key to a lot of what we are doing today.
The standard library uses it. Error handling is depending critically on it.
So what is it? Here's a type A user defined type A class.
It has two parts, the public interface and the implementation.
So basically this is one level of abstraction and that is a low level of abstraction on which it is built.
And you work that up and down all the way.
And I have given it this an element type, and it is you can construct this one by a list of initialises of its element type.
And here is the cleanup function. That's where you release the memory do so.
Here we can use it. I take a vector of doubles with some well-known constants and I take a vector strings with some well-known language designers.
I would like to point out I've been using this slide for years.
I did not put it in to Greenshoe this this is this is this is the way I do it.
And basically we get to the end, curly, here it goes and cleans up everything that was created by the objects in that scope.
And that's a very powerful abstraction mechanism. So we use it for just about everything.
In the C++ standard library, there's vectors, lists, maps, hash tables, strings and such.
They, they are all working on this model.
You acquire resources when you when you, when you create a variable and you release it again at the end of the scope.
And this is these are things that we acquire. It's not just memory.
There's things like thread handles, file handles, buffer capacities for for streams, locks.
And when we have smart pointers, we do use counts and things like that.
This means that if you can't just fire up a garbage collector and collect all the memory, not only would that give you longer resource retention,
because instead of cleaning up the mess, you leave the mess for somebody else to clean up later.
Therefore, the resource is held on for much longer.
Some experiments shows on average twice anyway, and this works recursively.
So if I have something like a catch it, which holds a five handle and a lock and such, and a vector of records that contains it all works recursively.
It works all the way. Okay, so let's take a more concrete example.
Semi concrete, that's a gadget I created with some initialise and I get a pointer out there.
This is the way we wrote code in the in the eighties.
This is the way they wrote code and Simula in the sixties.
There's nothing new here and we've seen too much of it.
But anyway, this is what we do. We don't actually know what this one does.
It's constructor grabs all the resources necessary for working well and now it's ready to use.
And we go down here and if this X is there, we throw something.
If X is that we return. And when we finished we delete the the the object again.
I mean we acquire using a new we delete it we release versus using delete.
However, as you see, sometimes we don't get there.
So people scream we want garbage collection because this is easy to forget.
It's easy to get wrong is particularly if we.
We don't get there. If we return, we don't get there. So there's leaks.
And so it comes that you don't really want news sitting out there naked and you don't
want the leaks being there naked because they correlate very strongly with bugs.
So we want to get rid of it. There's an easy way of getting rid of it is that instead of having the gadget made by New,
we have a function in the standard library called Make sure it makes an object of that type with that initialise and
return a SharePoint to a SharePoint as a counter pointer when the last SharePoint as shown object is destroyed.
The use count has gone to zero. It destroys an object it owned and therefore we will have to get it destroyed there, there and there.
And the problem goes away.
Except that now we have SharePoint us and we have use count and this violates the zero head principle because we have to access that use
count updating and release it in a multi-threaded environment that is actually a costly operation because it has to be synchronised.
And anyway, I, I don't want to create garbage.
I can't see any garbage here that needs to be collected.
I can't see anything there. Require use part. I have one pointer.
And it goes away. Why do I have to count?
Zero, one, zero? No, we can do better.
Actually, the simpler code is there.
You just take a local variable, control it and you use it, and the destructor would be called there, the end there.
Because when you go out of scope, the destructor is caught. Problem solved and the code is shorter.
And so don't use new in general code because they belong in resource management code.
So if I see a delete in your code, I assume there's a bug that you have too few too many deletes.
And if I see a new I know you need a delete somewhere, so I assume there's a bug in your code.
So this is much simpler and if you really need pointers that needs to be counted.
You don't know about ownership. Yeah, SharePoint is there. It's actually quite useful, but people all use it.
So this leaves us with one problem that is quite often we make a big object,
so lots of data and then we wanted to get out of the function that did it, get back to whoever requested it.
And this is what people use pointers for and they use free store, also known as dynamic memory or heap.
They used to that and then they send a pointer back and they'll have all the problems back again.
So we need to avoid that. So here I make the gadget from here, return it.
And conventionally when we churn something, that's a copy.
So basically here I call F and here we copy the and the G out to g g.
Now, I must point out that only a computer scientist could have thought of that.
So to get this one from here to there, you make a copy.
Over the end, you destroy your original. No baby.
About 4 to 6 months old. No. Here it is.
Now it's over there. Now it's back again. They can figure it out.
So we just have to make sure that that's what we do. So here is G.
It's a gadget. And if it's a big thing, like a matrix, a vector, a collection of stuff,
if the stuff will be over here somewhere on the on the free store and this is a handle to it.
So all we need to do is to copy the handle into g, g and the handle is this more?
If this was a matrix, it would probably be two words. If it's a vector, it's three words.
And then we cut the connection to the first gadget so the destructor doesn't get to throw away the good stuff and problem solved.
And so the cost of getting a megabyte of stuff out if you do it like this is, well,
2 to 4 memory assignments and now you no longer have to worry about pointers and memory management or share pointers and all of this stuff.
This completes the control of the lifecycle of, of, of, of objects.
Now, some of us have been doing this since the nineties, but it's only became systematic and guaranteed that it could be done in.
The and C++ 11. This is the handiwork of a guy called Howard Hint that found out how to to formalise that so that's easily done now.
Also, I'd like to talk about evolution to point out that I have never claimed C++ is an object oriented language.
It never was just an object oriented language is never meant to be just an object oriented language.
I don't think everything should be in class hierarchies or any of that stuff.
So she prefers not object oriented, is just object oriented for any definition of object oriented.
For starters, we need to deal with this direct mapping to hardware when hardware tends to be messy.
So we have to do things that that doesn't behave like objects in a real way.
They actually real world objects. And you have to obey their curious and somewhat perverse semantics.
So we deal with this. Furthermore, we want value semantics for some things.
So A, B, A becomes B means that they have the same value and modification of the one doesn't fix the other.
This is what we do for integers, for complex numbers, for points, for vectors, etc.
So that's that, that's that model has always been in C++ and it's one of the things we do.
Also, I want to say square root of two, not two dot squared.
I really think this is the nicest notation. This is the nicest notation and such.
And I don't want to have two versions of a of things.
If I, if I add a floating point number to an integer.
I don't want the integer class to have something that takes floating point numbers
and the floating point number in class takes something that takes integers.
I want the old fashioned 300 years old notations that furthermore, generic programming was always part of the C++ plan.
So that's doesn't fit with the object oriented thing.
So these days, the control of C++ is by an ISO standard committee.
And the way that happened was that representatives from HP and Sun turned up
in my office and explained to me that I wanted to standardise C++ with ISO.
And I said, Well, it's not ready, it's not finished, it's through a project.
And they sort of twisted my arm out and in the end I said yes.
The argument was that you could not have a language, major language, supported by controlled by a single company.
Everybody believed that in those days it has been proven untrue.
People are using Java and C-sharp, even though they are owned and operated by an individual company that might be your competitor.
Anyway, at the time, nobody believes that could be done. They had not thought about the advertising campaigns that could do it.
And the other argument was rather blunt Well, we will not trust you as your employer, and we will, of course, trust you.
But you could get run over by a bus. End of quote.
So I agree to standardisation. There's many kinds of standardisation and the ISO standardisation here is sort of the gold standard of standardisation.
It's thorough, it's open, and they have some rules.
And so we get long term stability, which is a feature, an important feature to many of the major users.
It's vendor neutral. It's really hard to sort of jargon or the C++ definition so that it favours my company rather than yours and such.
And danger is designed by a committee is horrible.
Stagnation could happen if people decided not to do major things because they couldn't agree on which major things to do.
There is divergent direction of design.
If you get sufficient number of people, they can't agree on anything and they have a tendency of or elaborating any individual feature.
You can see that in C++ in places. I'm not going to go into detail.
I'm just going to show you the picture of the committee. So this is what it looked like.
Then it became set. Then it became that. And this was earlier this year.
How do you get that group of people to agree of anything?
They come from different countries. Different industries, have different philosophies, have different education.
This is really, really hard. And I, I reckon this is a picture of my major problem with C++ today.
It is amazing that we have succeeded as far as we do.
But let's see. I'm going to talk the rest of time how we got from well about there till 20 years from now to three years from now.
So that's evolution. We got a new standard in 11.
The first one was in 98, then 14 and 17 C++ level was a major improvement.
This was what we had learnt over the previous decade and a bit.
Standards usually come every ten years. We actually took 13, which was one of the reasons we decided we can't keep on doing this.
So we decided we were going to go on a three year cycle and actually deliver what we had to deliver.
There's lots of new features in 11, lots of simplification.
One of the ways I'm working is that there's a language we can't take things away because of stability.
How can you make it simpler to use?
And the answer is have features that are simpler to use than the general ones and then have rules for how to use them.
Well, now people say, why don't you just throw away the old stuff?
Well, half of the pictures I had in the first two slides were break.
And people everybody wants two more features. And by the way, the language is too big.
You should make it smaller and don't break my code.
These are the sort of the hard constraints on evolution and we have technical specifications and such.
Now we have three major implementation implementers of C++ playing Jesus, C and Microsoft.
And by the way, they shipped essentially all of C++ 17 this year.
And the standard hasn't been signed off in Geneva yet.
The technical guys have done it and the technical guys have delivered the compilers.
A lot of you will be using them already. We are delivering on time.
This is spectacular. I mean, remember, we deliver on time.
Not as much as I would like, but we delivered. So C++, 11, ten years of experience.
Long list. You can look up the list. Wikipedia has some CGP references, lots of places.
I am not going to go into details. Going through the slide in any detail will take a day.
So we're not going to do that. I'm just going to show one example here of C++ 11.
So here I'm going to say the old problem in a container C I want to find all the elements that has the value.
V And what I'm going to do is I'm going to return a point of each of those elements.
And let's see an example here we have a string. A string is container of characters.
Mary had a little lamb here. And so for each pointer that comes out of find our as a result by giving it M and looking for the A's,
I'm going to see if the pointer really points to A if it doesn't do something seriously wrong.
Okay. So, so in other words, I want this to test whether that wasn't me.
That was me. That was me and that was me. The way we do it is we start a vector of pointers to elements.
In this case, the value type of C is character char and for each X in C sees the values, right?
If it is, push the pointer to the end of the result vector and return the vector.
Now, if this had been a C++ 98 program, we would have had a serious performance bug there because I mean,
a vector for elements is not that expensive to to pass.
However, I might have given it a megabyte of data and returned a million pointers and even modern hardware can feel copying a million pointers.
However, modern vectors do not copy.
They move. So that is dirt cheap. So the difference between C++ 11 and C++ 98, here is what you don't see.
You don't see any pointers. You don't see any locations.
You don't see any range checks. It's all gone away.
It's done implicitly in places, and it's done efficiently.
So that's what's different. So for 14, we finished 11.
So the point here is that when you have a large project before the end of the project, before the shipping date, you have a feature freeze.
And while the feature freeze happens, you learn things and you can't do anything about it.
So for us, the end of the feature freeze is about a year before you ship the standards.
After having a major release, you start using it and you learn things you hadn't guessed.
You do. And so the idea is after three years we have had the feature freeze.
We have learned what the effect of the the use of the features are, and we can fix it in time before the next feature each.
And that's how we got C++ 14. It completes 11.
That was all planned and it has lots of little things.
There's this year, for instance, the graphical people really wanted binary constants, so we gave them binary constants.
The OBI means it's a, it's a bit pattern.
Then we found that people can't read this stuff and you see what that is.
Okay. Then we gave people digit separators which are just for the humans reading the code.
We're always interested in things that simplify things by making bugs more, less likely.
And that's what this does. Lots of things here. Remember, we are still maintaining compatibility and stability.
Yes, we would like to get rid of some of the old crud, but we can't.
We've tried. So one of the things we've been doing in the Lake Framework, we had a lot of requests for being able to do more at compile time.
So a lot of people do the following.
They have some code and they need a value in there.
So they go to a tool to pat on the side and they calculate it, or they use the calculator and they get a value and they put it into their code.
Then you wait a couple of years and it's now the wrong value and you have a magic cast in your code and you have bugs.
So we had requests potentially from the embedded systems industry for doing better things at compile time.
They also sometimes want to put constants into run, and C++ wasn't good enough for that.
Actually, I think it was, but they didn't agree. So here is an example.
Somebody in the Japanese embedded embedded systems industry wanted an integer square root function to be executed at compile time.
So when we do that, we say that we want to have it so that it can be calculated at compile time.
Then we write the simplest algorithm we can find. This will be executed at compile time.
The compiler executes it to be able to do this trick.
The function has to be pure in the sense that it cannot have side effects and it cannot operate on any data that is in its arguments.
If somebody likes nice mathematical functions, just just require their context.
But that takes care of that problem. Furthermore, it allows the compiler to squirrel away the information necessary to do this.
And if it did, if for every function you couldn't compile a really big program.
So it's important that we have to say it. So we can now take the square root of nine and take it square with a one, two, three, four.
And we don't have to use a do pattern.
We don't have to do strange things with macros to do it. Now C++ supposed to do the basic stuff and then to handle abstractions.
So let's see, we can do compiler time abstractions. Here's a little abstraction.
It's a weekday of June 21st, 2016.
This is an example of use of my favourite data library.
This is is very nice. And it writes Tuesday.
We can do that at compile time. Let's take a static assert, which is an assert that is evaluated at compile time to see if it works.
So I'm saying that the weekday of June, the 21st, 2016 is a Tuesday.
And it is. So this assertion does not fire.
But if if I had been wrong, it would have given me a compile time era so we can actually do nontrivial computations at compile time.
By the way, this library is more efficient than anything else you've done for data.
So it's not this has not become elegant by being inefficient.
So 17 should have been a major release. The idea was to pick up the intel idea of tick tock, tick tock, major release minorities made enemies.
And C++ isn't 17 isn't. So if you hear me grumbling about the standards committee and slow rate of evolution of C++ and the many little features.
This is what I mean. This should have been great. It's only okay.
That is a little bit for everybody.
I think everybody will find something they like. The problem is that there are.
Maybe 80 different features. And if you like two of them, you still might have to understand the other.
The rest of them.
There's a nice parallelism library that's a variable type that's useful, some way of dealing with with with marginal return values and such.
This this is good. This good. But it's not great. So let's see, where do we go from here?
And we need a guiding philosophy for kind of this.
We can't just say, is this feature good?
Let's take it. Is this feature good? No, let's not take it. What are the criteria?
What are the direction for where we are going?
So basically my aims include complete type and resource safety as fast or faster than anything else, good on modern hardware,
whatever modern hardware is going to become, and significantly faster compilation even though we are doing better checking.
I don't think that's a modesty it and basically dream no little dreams.
That's his slogan. And the best is the enemy of good.
That's his slogan. I can't just dream. We're going to build something.
It's going to be useful. I want this to be useful in 2020 and I want the prototypes to be usable next year.
So we're going to do that. That's an engineer, right? So make C++ a much better tool for building demanding applications.
That is the ultimate aim. And these are the sort of more specific aims.
The challenge is I try to set the committee with the science.
So my philosophy is a lot of what philosophy philosophers are anyway.
So it is actually the only way of maintaining our direction and to have a coherent language.
This is absolutely essential and it's more a language is more than a collection of features and individual
feature can be great and just be a distraction in the context of a tape system and all the features.
We must do better. We must have a balance of features and basically we don't want to have a habit and the design rules are mostly non-technical,
and this is where it's hard to get through to the geeks.
I actually wrote up some design criteria in the early days, and here's from a book I wrote about it The Design Evolution of C++.
If you want to know about the early evolution of C++, you can read that book.
And I wrote two papers for the History of Programming Languages Conference, which you'll find on my publication page that also describes evolution.
It's all of these features I'm skipping over fast here because I only got an hour, but basically.
Drive by real problems. I think theory is great for solving a problem once you have decided that it needs to be solved.
I think theory is a lousy guide to what should be done and so don't have a stripe quest for perfection.
If I can come up with a 99% solution, I'm not going to wait two years, three years, a decade for the last percent.
And so there's things like this. You can read this for details.
And I'd like to point out two of the things documented in 94.
And actually, you could probably document them for for AG for all before no implicit violation of aesthetic type system.
Now, this surprises people who I used to see and such and even parts of C++.
But there's a difference between ideals and what you can get.
I'm going to get this one sooner or later, but I haven't got to get any straight, she said.
C++ is a strongly type programming language with weak enforcement very weak.
But the underlying system is the same, except possibly for some conversions that go both ways.
And anyway, I really want to eliminate the pre-processor.
So still trying to do that is really hard. There's people got a million lines of code and says, You're telling me to get rid of the macros?
Yeah, I'm telling you to get rid of the macros. And they, they, they, they laugh.
But I actually think we're going to get rid of the macros in something like the Windows kernel.
It's probably the worst macro [INAUDIBLE] on earth and that is why they have decided they
actually agree with me because that [INAUDIBLE] is what they have been living in for a while.
We are going to make progress. But remember this was early things. We are still working on it.
So what do we want? I want a major release in 20.
C++ 20. I want my definition of major.
Is it something that changes the way you think about programming, the way you think about building systems?
That's the definition of major. Minor is everything else.
And what can we get? I like science fiction, but I don't like to talk science fiction.
Everything on this slide actually has been implemented somewhere.
So it's all very mired science fiction. And by the way, that is a show of slides.
I really was very I thought it was very cool when I learned that Douglas Adams were programming in C++.
And so this this this this video game was written in C++.
So I want concepts, which basically is constraint generics.
I want modules faster and more hygienic compilations, code change contract.
I didn't know if, but when I wrote the slide, but last week I was told that the implementation has started in a university in Spain.
Static reflection there's a problem. We have three designs, three with implementations.
And now you have to have the community to decide which one to have.
And I really, really want them not to have the union of those three designs.
So that's that's what that question mark was for networking.
We have a really nice networking library close to optimal in many ways in widespread production use, better parallel algorithms, better futures.
We have the model of promises and futures for for sending information from
one thread to another without having explicit locking and all of that stuff.
We have it and it should be much better because there are some design errors in the C++ 11
design and I want a new standard library with the concepts here so that we get proper teaching.
Let's see how we do it.
If you go back and look at my very early papers from 81 or thereabouts, you'll see I want an object oriented programming as pioneered by Simula,
and I want that generic programming because basically I wanted a vector of cheese, which was something I could specify.
As a parameter. And once you have vectors of cheese, you want a sort of cheese.
What sort of victim of cheese? Where you have parameters for data structures, you have parameters for algorithms, for functions you need both.
Okay. So I conjectured that you could use macros for that.
That did not scale. Macros for generics.
It works for about two people and not much more, and it's one maintainable.
So in 87 I made a design of templates.
I wanted extremely general and flexible. I always want that.
I want zero overhead. I always want that.
So basically, I wanted something that could do more than I imagined and could compete with crazy and other basic facilities there.
And of course, I wanted well defined specify well specified interfaces because that's good and that's what we always want.
And two out of three ain't bad. I could not do that.
I don't think anybody in the Middle Ages could do all three.
If you look at all the languages that has things like that, they don't have all three.
So we can now do it. The way we do it is let's see.
The problem was that we got compile time duck typing and it gets very, very complicated and horrendous error messages you get wrong.
And it was very, very successful because of its nice features, flexibility, performance, etc.
We are trying to attract address this complexity by providing context for functions, functions that can be evaluated a compiler time.
So we do made a programming that is not to implement a programming.
If the result of a compile time computation is a value like seven, you want to call a function to get it.
And we want to specify interfaces. So here is an example of something using concept.
I want to sort something and I want to sort anything that's sortable this there's a
definition of what sortable somewhere you can look it up in the menu in the standard.
It's something that has is a sequence with a beginning and the end.
And it has elements. It has a lesson operator.
And it has random access to the elements.
That's it. So anyway, if I have one of those, I can sort it as it happens in the standard.
You can't sort a list this way because the list doesn't have random access to which elements.
So the way you do it is you just copy the list into a vector sorted and copy it back again.
That's usually the most efficient way of, of, of, of doing a sort of a list.
Now I can then say sort of actor and it says those make time.
All the properties required for should be sortable.
Yep. So we can call it. We can sort the list.
Does the list have all the properties that is required to be sortable?
No. Let's try this one. And the answer is yes.
And we just do it. And notice I am not saying that a sequence is less than sortable or something like that.
I'm just trying to see what works. And this is very simple over all loading rule.
If you match one thing, that's it. If you matched two things.
If the one is a subset of the other, you pick the largest end of rules.
So that works nicely, and you can specify your requirements like this.
A sequence. It requires that the type has an iterator that has a beginning and the end they have an iterator and
those generators are actually iterator is not just called generators in the story and concepts.
Sortable means that it's a sequence with random access with the order of value type.
I was just what I said this is of English so that that works by the way it's shipping in adjacency six point and higher or to seven.
So this is not really science fiction modules is another thing we're working on.
Compilation just takes too long. C++, we have to include model.
It includes all the text, you get a whole lot of text, then the compiler deals with it.
Compilers are superb at compiling a lot of text, but it still takes forever.
So we want to do better. We want to define modules here.
I'm defining a module called the map and. And the map printer.
To implement that I need airstreams, i need containers and I want to use namespace city.
Notice I'm saying import not uh, what you call to include and these export something.
The idea is that when you include you get what is exported and the module itself is a semi compiled construct that is self-contained,
semi compiled once and then expanded where necessary and that is very significantly faster than includes.
I have seen real live examples that compiles ten times faster.
So we're going four factors here. If I get five times, I will be happy.
If I get ten times, I'll get even happier. If you give me 40%, I'll be sad.
This is this is ambitious. And so here I am going to export a template that prints maps.
It takes a sequence, and the sequence has to have printable value type, the key types and a printable value type.
And then I do for all key value appears in print them out.
Now I want this to work. And she proposed 20. This works today.
It's called Structured Bindings. It's part of C++ 17.
This works in the Microsoft implementation, and the concept works in TCC.
When I first wrote this slide, this worked only in plan and see why I want a standard.
I want all three in all platforms I'm using standards are really useful.
So how do we go through to evolve? The language is getting bigger and more complicated and the users are more busy than ever.
So what I want to do is to answer the question, How would you like your code to look like in five years time?
And if you think very much like today, I think you're on ambitious.
You should we can do much better.
So I'm doing it tagging with a sort of a drug cocktail through language design, coding rules, a library and some static analysis.
And I'm after type and resource safety and I want to eliminate all complex techniques
by analysing complexity and throwing things out if they correlate with bugs.
And so basically, this is the Holy Grail I'm after.
There's a project called the C++ Core Guidelines, which is a joint project.
You can find the current guidelines on GitHub.
It's a joint project between Morgan Stanley, Microsoft.
Red Hat, Facebook and a lot of others, which you can look up in the contribution list on GitHub.
I encourage you to note Microsoft and Red Hat.
There's not many joint projects between those two organisations.
I think we have seen progress here anyway.
So what I want. It uses the guidelines and then has a small support library.
By small I mean about a dozen abstraction, similar ones.
And I want static analysis that is work in progress so I can write type and resource safe C++,
but I want it guaranteed and we are working on those guarantees.
But basically no leaks, no memory corruption, no garbage collector by the simple trick of not having any garbage, no limitations on express ability.
I don't want things safe by making sure you don't say anything interesting.
We need still C++, no performance degradation, so we can't just test things at runtime.
Still ISO C++. I don't want to design a new programming language.
It takes forever to build. It takes forever to get deployed.
Basically, the minimum penalty for designing a programming language that works is ten years of manual labour,
meaning you have to work on the manual for ten years. And I wanted to enforce it.
And so basically, I want to get rid of code like this here is innocent looking quote unquote with a delete in it.
There's a new Aquila function and I use it. This is disaster.
Because by the time you get down there, the object doesn't exist anymore.
So this one either reads some memory, which is not the object.
That is just the point I used to point to. It may actually write your favourite data structure and you have the most mysterious bugs you get.
The problem with dangling pointers in their use is you can't see them.
That's why I chose this picture of a nightmare. Never let a point out lived object is point to easy to see how to scale.
I mean, density said it's been there forever.
Okay, so once you get rid of that one, that's all about unions cost.
Not a point of view references. We can do all of that.
This, this this monster is less dangerous. You can see him and you can drain.
Drain his pond and your home. Okay.
Just to show this is not science fiction. There is a printout from the from from Visual Studio last year.
I have a track there that contains two pointers.
I make one of them here and the other the analyser objects because I'm throwing away the information that there was a new once it's up here,
the information is gone. Therefore, we have a potential leak and it will not like it.
So we are deploying this kind of stuff now and basically there's a lot of challenges left.
I didn't say C++ was a perfect language. Never have. I doubt I ever will.
There's lots of challenges left. The world is changing.
We must do better. I mean, our civilisation depends on.
Software. I mean, if if our software really broke, we will end up starving.
This is not an exaggeration. It's it's we have to do better than what we are doing.
And it has to be done on an industrial scale. And staying coherent is hard.
And so I reached my my limit here. And we have time for a few questions.