CppCast - Deducing This
Episode Date: November 11, 2021Rob and Jason are joined by Gašper Ažman. They first talk about some resources for learning C++ and learning how to work on the LLVM compiler. Then they talk to Gašper about the Deducing This featu...re coming to C++23, how the feature worked its way through the ISO committee and what it will change. News ADSP: The Podcast The Array Cast C++ By Example JetBrains CppCon Early Access CppCon 2021 trip report How to learn Compilers LLVM Edition Links p0847 Deducing This Defining Contracts Sponsors Use code JetBrainsForCppCast during checkout at JetBrains.com for a 25% discount
Transcript
Discussion (0)
Episode 325 of CppCast with guest Gaspar Ajman, recorded November 8th, 2021.
This episode of CppCast is sponsored by JetBrains. JetBrains has a range of C++ IDEs to help you
avoid the typical pitfalls and headaches that are often associated with coding in C++.
Exclusively for CppCast, JetBrains is offering a 25% discount for purchasing or renewing a yearly
individual license on the C++ tool of your choice,
CLion, ReSharper C++, or AppCode. Use the coupon code JETBRAINS for CppCast during checkout at
www.jetbrains.com. In this episode, we discuss some resources for learning C++ and compiler development.
Then we talk to Gashper Ashman.
Gashper talks to us about introducing this feature coming to C++ developers.
I'm your host, Rob Irving, joined by my special co-host, Connor Hoekstra.
Connor, how are you doing today?
I'm doing fantastic. How are you doing?
Doing good. It's good to have you on here.
Yeah, thanks for having me on.
Yeah, it's been a while since we had you on as a guest.
You've been on as a guest two times, I think.
And I believe since the last time we had you on, you have started your own podcasts, plural, right?
Yes, that is correct. So I think probably most of the people that listened to my first podcast are going to be familiar with me from that one because it has, I think, quite a bit of overlap due to C++ as our main focus.
So I started a podcast with Bryce Lelback, who I think you had on just a couple episodes ago.
That podcast is called ADSP, which stands for Algorithms Plus Data Structures Equals Programs.
And then there's a second podcast that focuses less on C++
and more on array languages like APL and J.
That's with a panel of four different people.
That's pretty cool.
I'm not familiar with what you mean by array programming languages.
What does that mean?
Well, very, very briefly, APL was a language created back in the 1960s
by a guy named Ken Iverson.
And it led to a very sort of niche community.
It was big back in the 60s and 70s, but sort of died out.
And its most popular sort of form of it exists in Python libraries like NumPy and Pandas.
So those were largely inspired by array languages.
So the main thing about array languages is basically there's only one data structure and it's an array like multidimensional arrays. So there's no hash maps, no, you know,
uh, you know, red, black trees or any of that stuff. Um, so yeah, I, I love it. Uh, if people
are interested, they can go check it out, but, uh, I won't say more than that because that's,
that's a whole other topic. Okay. Well, I'll make sure, uh, we get links in the show notes
for this episode for, uh, for the podcast. Okay. Okay? Awesome. Cool. Well, at the top of every
episode, I'll let you read a piece of feedback. Last week, we had Cy Brand
on. We were talking mostly about Visual Studio 2022.
We got a lot of comments on Reddit. I was going to quickly
read through two of these. One was, does IntelliSense work for
modules yet, and how about for imported
headers? I believe
IntelliSense does work for modules in
VS 2022, at least in the final release,
which is coming out today
as we're recording.
I believe Cy did a demo of that
in their CPCon talk.
Yeah. And the other question was
someone was asking, is there any difference from
the free community version instead of paying literally over $1, I think the criteria is like something
like over five developers
you're supposed to be paying for a license.
But if you just want to try something out for yourself,
definitely use the community version.
Yeah, I've used both in the past
and they're both great.
Yeah, I don't think you're missing out
on a whole lot of features
by just using community.
I think the main thing is just that
if you work for a company
that you're supposed to be using
professional enterprise. Okay, well, we'd love to hear your thoughts about the show. You
can always reach out to us on Facebook, Twitter, or email us at feedback at cppcast.com. And don't
forget to leave us a review on iTunes or subscribe on YouTube. Joining us today is Gajpar Ajman.
Gajpar is currently working on core libraries for research and trading systems. In the past,
he's worked on large-scale distributed systems, such as the Amazon Retail Search Engine.
He's a member of the British Standards Institute C++ delegation and has been a part of the C++ Committee since 2017.
He's fixed some proofs in Stepanovs from mathematics to generic programming,
published C++ The Beast is Back with John Kolb, spoken at C++ Now,
and is an author of Using Enum, which is a C++20 paper,
deducing this, ordering customization points in C++20,
and is currently working on contracts for C++26.
He lives in the gothest part of London next to the magnificent Abney Park Cemetery
and his friend DeCroze.
Gosher, welcome to the show.
Greetings.
All right.
Yeah, that was honestly the longest bio that i've ever had i'm supposed to ask the uh the jason turner follow-up question about the bio but i'm actually
going to ask uh something that's not in the bio that i just happen to know about you that i'm very
very jealous of uh you're one of the few people that i know sort of uh in my age bracket that
got to work with a Stepanov, correct?
Yeah, I did.
I worked with him for two years while I was in Dublin.
I got to go to Palo Alto quite a bit and work with him.
I was at the infamous Palo Alto meeting of the concepts proposal where you know sean parent came to visit alex and they talked
about how to you know structure concepts so it won't suck and uh we all know the history of that
one um they they do not suck, mostly.
We actually wrote quite a bit of pseudocode at that particular meeting.
That was really fun.
I mean, obviously, I was a super junior
and did some of the grunt work
of coming up with examples
for the Grand Minds meeting
in the biggest meeting room
of our Palo Alto office
when I was at A9. But, you know, I got to learn a lot, which was great. And then after I actually
moved to Palo Alto to be closer to the mothership, as it were, I actually, you know, like I spoke
with him quite a bit, like I went up to his office his office you know a lot and he just talked about stuff he
actually interviewed me for a night which was super fun i think it was a three-hour interview
which started with uh me asking him what he thinks of ranges uh as as implemented in d and he muttered
something i wouldn't report uh and and we ended at old church slavonic and how you dry
prosciutto like it was actually really really like all up all around cool interior it's probably the
coolest interior i've ever had um yeah it was fun yeah i'm very very jealous of that opportunity
it's not once in a lifetime but it's i don't think you know yeah steppenhoff isn't working anymore so it's something that yeah i would i would have loved to have the
opportunity but very jealous of you thank you i'd be jealous of me honestly
okay so uh gosh we got a couple news articles to discuss uh feel free to comment on any of these
and we'll start talking more about the uh deducing this proposal and maybe some other work you've done.
OK, so this first one is a new website, CPP by example dot com.
And yeah, just a new resource for looking at examples of how to do various things in C++.
It seems to be pretty well put together. I looked at the about page and
the author was saying how they're choosing to only cover the previous version of C++. So currently
all the examples here are C++ 17 and they plan on adding C++ 20 examples once 23 gets published. Yeah, I took a look through some of the examples,
and they're super nice and concise.
I really like that.
I really disagree with the ConstWest style, but I'll survive that one.
The last thing that I think about
this is something they really should fix
it suffers from the the problem
if you've ever had
a really large library
of music like have the
band start with the
and so music programs have
started ignoring that as a stop
word in alphabetical sorts
and this one has a
similar problem with how-to.
How-to, yeah.
They should really just ignore it in the
alphabetical sorting of examples.
But other than that, I think
it's an excellent
compilation of
just things that
the newcomers to the language
get stuck on. And it's an unsticker.
I love it.
It's a great project.
That's funny.
Yeah, I took a look as well.
I agree, it's a great resource.
I wish it had included the C++20 stuff
because there was a couple times,
like specifically when they're talking about
looking things up in containers,
like there's the new contains method
that it's very sad not to see that because
it's like explicitly what a couple of times in the code examples is used for. And then another
thing that stood out was the entry, how to add to an array. And I was like, oh, like that's not
possible because the std array is literally fixed size. But then immediately when you click on that,
they say, oh, that's not possible. You have to choose a vector, which it's interesting that that's like they didn't make a mistake there,
but they still left the title as it is, I guess, maybe array is known as non fixed size and other
programming languages. But overall, it was, I think, pretty great. Honestly, I think that's a
really, really great thing that they did. Because the way everyone will navigate this page is by control F. And at that
point, the title has to have what control L will find. That's true. Okay, next thing we have
mentioned Timur Dumler a few moments ago, I think this is his trip report for CppCon 2021.
He has joined, I think rejoined,
JetBrains now as a developer advocate,
and he was giving his perspective as an in-person conference attendee.
I think I did a trip report,
a registered report last week
that was from one of the virtual attendees.
Did either of you make it in person
to CppCon this year?
No, I couldn't have if I wanted to.
Timur has some very useful workarounds
for being able to fly there this year from Europe.
I did not attend either,
neither virtually or in person.
I heard great things about it.
And also too, I'm not sure do we do either
of you know what jet brains does because like previously uh they just used to release the
talks on youtube but now now they're released uh through like a third party site with like private
links and uh i don't actually know so maybe jet brains can i'm sure there's someone from jet
brains listening to this right now and they can tweet.
Like, do they all get released at the same schedule and just through a different portal with private links?
I didn't realize it was JetBrains releasing this. Are you talking about the CppCon 2021 videos?
Yeah.
So I think since maybe last year as well, like JetBrains has a new sponsorship deal somehow that for a certain period of time they don't get publicly listed
it still all goes through the cpp con youtube channel but like that's how i consume all my
online talks is just through youtube but now uh i think jet brains has some sort of mechanism where
they list them privately and get the links and then they do it through some portal but i can
never i can never figure that out like uh so jet brains
add us and let the community know how do we watch these talks um i mean i know the like the keynotes
i believe have all been published and i saw links on reddit but you're right i'm looking at the cpv
youtube page right now and i don't see any listings for 2021 but i know they're out there
yeah exactly yeah i think the most recent one is from three months ago and is not a 2021
video.
So,
uh,
interesting.
Okay.
Yeah.
We should definitely figure this out and,
uh,
let listeners know the best way to find the CP con content that's already up
there.
And I'm sure the rest of the videos will be coming soon.
Usually I think it takes a couple of weeks to get all of them out,
but they get the keynotes right away.
Yeah.
Yeah.
I was really hoping I could watch Ben Dean's talk on deducing this before this
interview,
honestly,
to like crib off his notes.
If you're an avid talk watcher,
and this is why I was so curious about the Jetbrain situation is I happen to
know that Ben Dean gave a version of that talk at the North Denver C++
meetup.
And if you know their YouTube channel,
which is very small,
it's only got like 86 subscribers,
there is actually a version of it online right now.
We can link it in the show notes.
So yeah, I'm not sure when that's coming out.
He gave it at CppCon.
I'm sure it'll be the same talk.
But there is a version that exists online somewhere
if you know where to look.
Cool.
Okay, and then the last thing we have
is a blog post about
How to Learn Compilers LLVM Edition.
And it's just a good collection of links
for anyone who wants to get started
in understanding how to get into compiler development.
These are a bunch of shorter articles
and videos that you could watch
instead of reading maybe a huge book depending on what your style of learning is.
Seems like a good resource. I know this is not something
I'm looking to do myself, get into compiler development. Either of you
have any interest in this stuff? Yeah.
It is a really surprisingly comprehensive,
very short list for the really, really enormously broad topic that it covers.
Like having written some compilers myself, although nothing as fancy as LLVM. Sure. It is pretty much
the starting point for every
part of the compiler.
You may have broken it down by front-end versus
back-end, so if you're only interested in
either of those, you could just focus on
reading those resources.
Yeah, but the mid-end is where all the complexity
is. Sure, front-ends
are complicated,
but usually they're well-specified.
The midend is dark
magic. I feel like we haven't really
discussed the midend. What exactly happens
in the midend? Well,
the frontend gets you the
initial
intermediate representation,
right? Like, it takes the C++
or the Rust or the C
or the Ada or whatever the hell human-readable mumbo-jumbo you have and turns it into something that university professors understand, which it in a symbolic representation is because all of this fancy research on the other end, which it from, you know, one way of representing the program to a much more streamlined and hopefully faster to execute way of representing the program.
This is where you do loop unrolling and, you know, inlining and all of those fun transformations that eliminate a whole lot of work, such as not computing values that never get used,
figuring out that you can transform a whole loop
into a recursive equation
that then gets executed in a finite number of steps.
All of that stuff is done in the middle end
because all of these optimization passes
work on the same language
and then you give it to the back end thing that really like mostly just takes the intermediate
representation if it's rich enough and an llvm it is rich enough and makes it into native code
assembly and then there's a few people optimization passes to really find you and the outputs
to whatever platform you're running on.
But all of the really fancy stuff happens before that.
Interesting. Thank you.
I can also second this is a great,
super short comprehensive list.
I mean, I've heard of probably half of this stuff
and half of it haven't.
In the general intro section, there's a free Alex Aiken course.
He's a prophet Stanford on compilers that I worked through while I was at Amazon.
And it's a great resource.
And I haven't worked through this one personally, but the backend resource from NAND to Tetris
is a pretty well-known resource that I have a couple of friends that have gone through
and they say it's fantastic because you basically go from like nothing to building up a Tetris game. So you end up with a really,
really comprehensive. I mean, if you go through the whole thing and don't give up,
you end up with a really comprehensive understanding of like every level, which is which is great.
All right. So, Gashper, I know we've mentioned introducing this proposal before on the show.
I don't think we've ever gone into it
in any depth. And I don't know if you remember this, but I think like three years ago at CPPCon,
when it was still being held in Seattle, Jason and I and yourself and a couple other attendees
and speakers, I think went to dinner. And I remember you speaking very passionately
about deducing this. And it was kind of just like whoosh over my head so i was hoping
you could maybe start off by giving like a high level explanation of what the deducing this
proposal is oh i'll do you one better later on i'll i'll regale you with the story of um
how before that dinner me and ben dean uh went to lunch and came up with the whole thing so that's when he started
getting on okay interesting yeah yeah so so but to explain the proposal first and at this point i
kind of want to stop calling it a proposal because it is a c++ 23 feature unless a national body objects at the
last minute to actually passing
the standard, which
won't happen because there's no actual serious
objections to the feature.
So yes, there is a procedural
step still that could be invoked,
but it won't.
So in the end,
member functions are
functions, and functions have parameters. And when you end, right, like member functions are functions and functions have parameters.
And when you call a function, you supply arguments to match those parameters.
And then the body of the function gets executed with the arguments, you know, having the names that have been matched.
That's probably true of every function call ever. And for member functions, there
is a parameter
that behaves sort of weirdly,
which is the object parameter.
At
this point, up until this
one, did C++ have this weird name
this? That's why we call it the
implicit object parameter.
It is there whether you like it or
not. If you don't like it,
you need to mark the function static, and then it behaves totally differently, right?
And when you have an expression like x.foo, then that x gets matched to the implicit object
parameter, becomes the object argument, and then the body of the member function gets executed. So deducing this is really just a way to say, to mark one of the parameters to the function,
in this case, the first one, as the object parameter. So this is the one that you match
the object argument to, instead of matching it to the implicit object argument
that's it like and and in practice what this means is that instead of writing foo without
arguments you say this my class name self as the first argument and that's it like that that
function will now have a body where self refers to the x instead of this referring
to the x. And you can't use this inside that function anymore for various reasons, which we
can get into later if we want to. But yeah, that's really it. You designate one of the parameters to
the function as the object argument. And that's how matching
happens for that function. Now, that seems like a pretty minor change, and it is, but it leads to a
large number of places. Because since you now have a place to name the argument,
you also have a place where you can write the type of that argument. Before
the type was implicit because it was given by the class that the member function was contained in,
right? But now we can write the type and we can be boring and write the same type and then put
our ref next to it. And then, you you know everything happens the way it used to and
it's all fine um we could write the qualifiers for the implicit object parameter before uh in
c++ 20 for instance you put them behind the parameter list for the member function right
that's that's what the const ref after the parameter list looks like. That's really the qualifiers for the implicit object parameter, right?
So now we can just write the qualifiers right there in situ where they belong realistically.
That's why we can't write them redundantly at the end anymore if you have this parameter let's say um and because you can name the type if you make
the member function a member function template you can now deduce the type using normal language
rules um nothing surprising there but this turns out to be a huge, huge deal. For instance, if you are in a base class,
if this is a member function of a base class,
member function template, I should say,
and you are calling the member function on derived,
the deduce type, just like for any other parameter,
is going to be the derived one,
which means we don't need the curiously recurrent template pattern anymore.
This suddenly takes mixins from being a language feature
that you need to understand templates to understand
to anyone can write this,
and it just works the way you'd expect.
You don't even need to write template anymore
because since C++20, we have auto parameters, right? So if you just say
this auto ref ref self, that's it. That's all you need to do. Self now behaves pretty much the way
it would in Python. Hooray. It gets better because you can concept qualify that auto, right?
Mm-hmm. Which means this member function only works for derived classes
that also model this concept.
And you can constrain your mixins that way.
And it'll just work the way it's supposed to.
It does what you want it to do, basically.
And it doesn't read weird, which is, I don't
know, I just find it great.
It's really useful for also every place that you needed to perfect forward the object parameter.
Like the classic example for this is implementing, you know, the get method of optional or the
star member function of optional,
like the star operator, the reference operator,
because you need to perfect forward
the return value qualifiers
to the actual value that you contain.
And this is actually a lot more common than people think.
Every time you're forwarding a member function call to a data member of your class,
you should be perfect forwarding the reference qualifier.
Like, for instance, the vectors front and back should really be overload sets that had four different overloads.
They're not, but they should be.
Because if your vector is an R value, like going out of scope, why shouldn't you move out of the first parameter? Right out of scope why shouldn't you move out of the
first parameter right sorry why shouldn't you move out of the dot first um and the same should be
true of any accessor to vector like if you're if your vector is an r value and you only need that
one element please move out of it that should just be done if you're forwarding something um even if you have some kind of a callback which is another
whole topic um and you're scheduling a part of that callback to happen again like you have a
data member that needs to like you have some string that you need to log or something and you know
you're not going to need anymore um you should be moving that string into your logger callback or whatever.
But what if your callback doesn't know if it's going to be called again?
Well, if it's being called as an R value, it's not going to be called again.
You can be pretty sure that it's going to go out of scope
after the operator parents finishes.
But if it's called as an L value, it very well could be called again.
And in that case, you have to copy.
That was actually the original motivation for this paper, because in lambdas, you cannot actually do that, right?
Like in lambdas, you don't get qualifiers on your call operator, which means you cannot distinguish whether a lambda is being called as an L or as an R value.
And I can get back to that later when we're at the store.
So if you think about it, again, this gets us to recursive lambdas.
A lambda really is just the closure object with the function that you write in the code being the operator parens of that closure object.
And really, that's how they're specified, that's how they're implemented, that's how they work.
Which means that if you supply this auto ref ref self parameter to the lambda,
you can now get at the closure object itself.
Now, you still can't refer to members because they don't have defined names, and they might not even be there. That's a whole thing. But there are a few things
that the lambda itself does support. For instance, calling it. Kind of obvious that you should be
able to call a lambda. So you can call the lambda recursively. Another thing Lambda's support is moving them, right? Lambdas are
movable. Some of them are copyable, or rather copy-constructible. They're not copy-assignable,
so they're not copyable. But they are copy and move-constructible, which means, let's say your
Lambda's a callback. Your closure object is holding some resources that the callback needs.
And let's say your callback gets called. It's
currently being owned by the execution system that it's residing on. And it figures out that
it actually needs to be called again. Either not all of your input has arrived yet and you need to
be called again on the remainder, or maybe the timer has expired too early and you need to reschedule the timer to be called again
once the event actually happens or whatever.
Maybe your connection's not dropped yet.
Fine.
Up until now, you couldn't make the decision of
do I just return and not reschedule myself
or do I reschedule myself from within the body of that lambda?
Because the lifetime management of your callback system
wouldn't be able to handle that.
But now that you can get in the body of the lambda,
you can just call schedule again,
move the closure object into the schedule call.
So you move constructed object into the schedule call. So you move construct it again into the queue
or whatever your schedule system is using
and let the current closure always get cleaned up.
Done.
No more design space there.
You can streamline a whole bunch of branches.
It basically gives you the design space back
for the lifetime management.
And this didn't used to be ergonomic so people didn't do it like they they had additional restrictions
like you needed to return a boolean like yes i want to be cleaned up or no i do not want to be
cleaned up or whatever from the from the call right um now there's no need to do that. Like my homegrown scheduler actually has a Y combinator built in because it didn't want to make people return a Boolean.
So basically, when you write a lambda, you get your own object as the first parameter so that you can move, construct yourself into the next call if you want to.
But people
don't understand what a Y Combinator is,
number one. So the ergonomics of that
are somewhat doubtful without
inducing this. And it also takes a whole lot of
template metaprogramming to do correctly.
So I'd rather not do all
of that.
I love combinators, but yeah, the Y Combinator is
I think Vittorio has a
pretty good blog explaining it um but yeah not not my favorite combinator although it is a cute
trick to show the you know lambda and c++ using a y combinator but ideally there's a better solution
and it's showing up in c++ 23 yeah exactly we don't need the Y combinator anymore. We haven't built into the language and it doesn't
read like Y.
Because Y is the appropriate
response to seeing a Y combinator
in code.
There's another really, really
cool consequence that only showed up
with coroutines.
Coroutines of
free functions work well enough.
The one
thing with coroutines is that
you should really be taking all of
their arguments by value
because you need to ensure that they survive
until the coroutine
exit. And if you're writing
a generic coroutine, that means you
can't rely on the environment ensuring
that, which, you know,
like leads to a lot more pitfalls for dangling things. And it's like super annoying. So taking
things by value by default with coroutines, probably a thing you should do. Unfortunately,
there used to be one one parameter in the language that you couldn't take by value. And that's the
implicit object parameter, like it's always a pointer. With deducing this,
if you don't write the ref
at the end of your type,
it's not a reference.
You take your object parameter
by value, because that's what the language
says happens.
That's what it
looks like. That's what happens.
Which means that you can now
safely write coroutines as member function, and you're not going to leak your objects.
Yeah, that's really nice.
Right. It is really cool.
And that is something we didn't foresee because coroutines weren't a thing when we were designing this.
And it just so happens that it solves that, too, which, you know, is true of any good proposal.
Like it integrates with the rest of the language
so seamlessly that you're like,
why the hell wasn't this before?
And, yeah,
to sum all of that up, though,
deducing this
makes member functions as powerful
as free functions, but keeps the nice syntax
of member function calls.
And that's really it.
There's no
other weirdness.
We just unified a bunch of the
parts of the language and now
they're no longer annoying to use.
Want to wrap the discussion for just a moment
to bring you a word from our sponsor.
CLion is a smart cross-platform
IDE for C and C++ by JetBrains.
It understands all the tricky
parts of modern C++ and integrates with essential tools from the C++ ecosystem likeBrains. It understands all the tricky parts of modern C++
and integrates with essential tools
from the C++ ecosystem,
like CMake, Clang tools, unit testing frameworks,
sanitizers, profilers, Doxygen, and many others.
CLion runs its code analysis
to detect unused and unreachable code,
dangling pointers, missing typecasts,
no matching function overloads, and many other issues.
They're detected instantly as
you type and can be fixed with a touch of a button while the IDE correctly handles the changes
throughout the project. No matter what you're involved in, embedded development, CUDA, or Qt,
you'll find specialized support for it. You can run debug your apps locally, remotely,
or on a microcontroller, as well as benefit from the Collaborative Development Service. Download the trial version and learn more at jb.gg slash cppcast dash cline.
Use the coupon code jetbrains for cppcast during checkout for a 25% discount off the
price of a yearly individual license.
Sounds awesome.
Do you want to talk some more about the original inspiration when you
started working on introducing this right right yeah so uh it was cpp con 2017 and uh i was young
and you know happy um and i was at cpp con i was meeting all of the cool people and I had met
Bandin a few years before and
we caught up in the hallway after
I think
it was
Alexandrescu's keynote or something
something like that
we were in the hallway, we wanted to go
to lunch and he said, you know what's
really bothering me
these days? i can't
know from a lambda whether i'm being called for the last time because i'm returning a bunch of
things and i want to know if i can return them by move or do i have to return by value which would
copy and it's inefficient and i just like it really grinds my gears. Ben is like that. He wants everything to be perfect.
And I said, you know,
if you could figure out the qualification
of the lambda function call,
then you'd be able to do that
because you'd just be called as an R value.
It really is the R valueness of the closure object, isn't it?
That's really what we're-
What if you were able to just get-
What if you were able to name your closure object?
I remember having this epiphany when I walked right through the door of the Maiden Bower Center,
where CppCon used to be.
And that's when it clicked.
Like, yeah, of course, you should just be able
to name your this parameter and know the qualifiers on it. And then we sort of hashed out the syntax
at lunch. And it wasn't the current syntax was worse. And then we had a few more dinners with some other people.
And yeah, that's
how we
arrived at, we should write a paper.
So we did. And then we shopped
it around. And
I, for the life of me, couldn't find who
said, you know what?
Barry and Cy Brand are
writing pretty much the same paper.
And I said, they are?
Let's get in touch.
So I get in touch with Barry over Twitter.
As we all know, all committee business is done on Twitter.
And it turns out they started from a completely different place.
They didn't start with the value category of lambdas and recursive lambdas.
They started with optional.
And how annoying it is to have to write four overloads
of freaking every member function of optional,
especially since Cy was already working on monadic optional
and dot then and all of those maps and things like that
need all the forward in order to be correct.
And so it was just a mess, right?
And not only was it a mess, it compiled slower
because you needed to forward to another free function that implemented your logic so that you
could prove it and then just do the casts. And if you use std forward, that's more
function instantiations and it's horrible at debug time because you have to jump,
like in a debugger, you have to jump through all of the std forward
which is amazing.
And so on.
So
Cy was really pissed about
optional and I was really pissed
off about lambdas because
all the committee proposals start because
somebody's pissed off about something. We're a very angry bunch of people uh and that that that's why we do a whole
bunch of work um over years the anger does not subside until the work is done um yeah so so
anyway they had a different syntax in mind because they started from a different place.
And so it ended up that we went with the syntax that me and Ben were proposing in our paper.
We ended up using their paper number.
And then there was the whole saga of how do we get this through the committee?
So when we first merged the papers uh barry was
planning to present it at ewg and we uh shopped it around a bit and there was a lot of resistance
what committee meeting was this at do you remember oh god no you know what year it was
well it would have been 2018 but i think it happened after my C++ Now talk
because once we wrote the paper, we realized
that there was a lot of resistance and we didn't even present it. It was
just like, oh, this is new novel syntax and people are like, why
are you doing this? This seems like it's not useful or
something. I said, okay, wait until
C++ now. Let me present this. Let me actually have like a proper hour, like, what was it?
Three hours? No, it was an hour and a half that went over by like half an hour.
And the C++ Now crowd loves to hackle, which is great because you iron out all of the problems with proposals. And so we had this
extended presentation at C++ Now where I not only presented the paper, but like four different
extensions that we're planning and why the syntax needs to be the way that it is,
and so on and so on and so on. And we ironed out quite a few problems and we were able to actually listen
to people's issues with it
throughout the week of C++ Now.
It ended up being a really great time
to iron out things
and also to socialize the proposal.
And the reason you need to socialize
novel syntax, I find,
is because committee people
are still people and human brains do not like change and we're always like oh then there's
another thing i have to learn why why are you doing this to me i don't need it um but it turns
out that when you present something and then three months later a person sees the same thing recognition turns out to be a really positive emotion and so people when they saw it again
were like oh yeah i've seen this i understand this and it's a it's a neat feature i kind of
like this and so this i kind of like this went in several waves throughout the committee. And it's really funny how every single person
seeing this paper comes up with the same objections at first.
And when you explain to them what the problem is
with the alternative proposition that they're making,
they're like, oh, but this.
And it's one out of the two predictable things.
And then you just work through the graph
to the same place where we ended up um and the funniest thing is that's where we start
like the paper authors that's literally where we started so when this was first presented at ewg
they did not like it um so we presented it again with you know having done more research like the committee is always happy
to approve more work right um so we did more work we presented it again there were four syntaxes
in that second iteration and the committee the ewg had a poll about which one they liked the
most after the presentation and predictably picked the wrong ones. And so then all of us four authors went,
oh my God, why?
Okay, we're now working on a paper
where we don't like where it's going.
This is not what we signed up for,
but let's just write it.
Like it's better than nothing.
Fine, like EWG wants it that way.
Let's do it that way.
And we did it that way and it was like wrong.
It was so wrong that we were like, no,
we need to somehow reverse this.
Fast forward to CppCon
the next... That was now
2018
CppCon, I think.
The start of this went pretty quickly, I think.
And
I get a
stop herb starter in the hallway.
He is the committee convener for anyone who doesn't know.
Also really an amazing mind.
And I explain to him the issues,
and he predictably comes back with the same graph of things
that I've already talked about.
And we walk through the graph in an hour and a half,
which, to his credit, that's incredibly quick
to get through all of the phases of deducing this design.
And he says, yes, I see.
EWG really did make a mistake.
I believe that this can be reversed.
Why don't you talk to Ville, who used to be the chair of EWG at the time, and figure this out?
So I take Ville to lunch. Fortunately,
the CPP gone. Everybody's there
and it's not a committee meeting, so everybody
has time, which is great.
So, over
eating a sandwich, I explain to
Ville what happened
and ask him
what we can do about this because this is going the wrong
way. And we have polls from EWG
and he said, ah, Gaspard, don't worry, this is material new information.
Write that into your paper.
Present the syntax as you want it to be, and I'll schedule it.
It's good.
So we get rescheduled with material new information,
which basically was just, y'all are wrong, please reconsider.
And they did.
So after that, we were basically clear on DWG,
but because the paper had changed so many times,
everybody was super scared about passing something
that wasn't properly vetted and didn't have an implementation.
And there were issues that turned out not to be substantiated
over the implementability of the recursive lambda part.
There used to be a recursive lambda proposal that was an alternative to this one.
Turns out it wasn't implementable for various reasons,
but the main one is in the other recursive lambda proposal,
which gave the lambda object a name outside of the parameter list, you couldn't do size of the closure inside
the lambda body because that turned out to not be computable without solving the halting problem.
Turns out with deducing this, you can't actually name the type of the lambda inside the
parameter list
because it always has to be a template.
But the other proposal could be a normal function.
So with deducing this,
it always has to be a function template
because the lambda body isn't formed.
There's no way to get decltype of it at that point, right?
So there's literally no syntax you can use
to divine the type of the lambda,
which means the size of expression is dependent and
everything magically works.
So it took me another
few months
to CPP now the next year
to sit down with David van der Woerde
and explain to him how that works.
And then at that point, he had
enough information to say, yes, I believe
this is implementable. And then Barry
sat down with him a few months later and
implemented it in EDG,
the EDG compiler.
And so when the implementability
of Lambda issues solved, we got
seen by EWG again, and
they approved it, but said, you know what,
we're still uneasy
about this,
and then we got seen by EWG again
the next meeting saying, we have nothing more to
say really like nothing happened in these three months we did some more research it all works
we've got wording um so should should we just send this to core and ewg sent it to core and
yeah that a few votes later here we are in c++ 23 it's it was a saga yeah it's interesting because i
primarily sit in a library uh and so i i don't often sit in language even though it's all virtual
now so it's whatever just sitting in your own apartment um but my view and this might be biased
because i speak to ben quite a bit is that there was like uh you know the deducing this paper
at least towards the end had like pretty good consensus.
And like,
it was one of the least controversial because of how well it played with all
the other,
like it's,
it's very rare to have a new language,
like something on the language side that just works with almost all the other
existing language things.
And because of that,
there wasn't too much,
you know,
controversy about this getting in, but it sounds like that is not the way it started. existing language things um and because of that there wasn't too much uh you know controversy
about this getting in but it sounds like that is not the way it started um that it was a long
uphill battle um for for what ended up being or i don't know is it still controversial at this point
or no i'm not even mistaken okay yeah so it it got consensus but it took years. It got years for people to get familiar and comfortable with the original design, basically.
Interesting.
Which is not how most paper goes.
Like most papers go through a lot of iterations where there's tweaking and so on.
This paper pretty much got born and then elaborated until all the FUD was gone.
FUD being fear, uncertainty, and doubt for people who are...
So what are the top things developers should know when C++23 comes?
How will deducing this make their lives simpler?
Is it the CRTP pattern is just going to go away
and you can write that type of code a lot simpler?
What kind of things should we highlight?
I think that it really depends on what kind of code you're writing okay like for me the code that i write like 20 of my
code base is just gone uh because it's mostly forwarding through various layers and like simple
program transformations that have so much forwarding and forwarding and forwarding and forwarding.
I did a quick survey before the show,
and actually half of my function calls are going to be gone
because I don't have to forward through an additional layer anymore, even.
So it'll compile way faster.
There's no more overload resolution between four alternatives anymore, so it'll also compile way faster. There's no more overload resolution between four alternatives anymore, so it'll
also compile way faster.
And also not having to write that is
a huge win.
Yeah, it's a huge
win, but I write
domain-specific languages.
I write libraries that connect
various components together.
Specifically this year, I've been writing
lock-free schedulers.
And that's all about shaving off every cycle you can through inlining.
And it turns out that forwarding
is a really good way to inline things
because the compiler sees that,
yep, this expression really is type identical
to that other one.
And it has the same pointer, done, right?
That's not true for a lot of my colleagues who
don't write function templates all that often. And for them, not a whole lot
is going to change. For people who write a lot of type
erasure, things get really interesting because of by-value parameters
because you suddenly don't have to erase four
overloads. You erase the by-value one and expect the language to move.
And that allows erasing factories
that basically wasn't ergonomically possible before.
And that's why nobody did it.
There's a whole lot of things you could do in configuration
that you couldn't before,
just because the code ended up being so horrible.
But yeah, other like giant code reductions it doesn't enable a whole lot of things um but because it makes so many things that we used to do a lot easier i think that uh there's going to
be a lot of emerging patterns built on top of this that we just didn't like some of us did them in spite of the language because we had to
but i think a lot of these advanced quote-unquote patterns that we used to uh leave to the library
authors where speed was important we will just expect normal uh everyday programmers to just use
because they're now nice. They're no longer horrible
hacks, effectively.
So I think that it'll streamline that,
but it won't change.
I mean, it might change the paradigm
down the line when people
adopt the new idioms,
but who knows? Idioms are always emergent.
For folks that are interested, too,
on top of Ben Dean's talk
that'll be on CppCon and that's on the other YouTube channel, the paper itself is littered with like before and after Tony tables or whatever we call them.
So if they're curious of what the difference is, like a ton of it is like, you know, it's it's like a fraction.
The after table is a fraction of what it is on the left.
Yeah, it looks it looks awesome.
Very cool.
We're running a little bit low on time,
but I did want to quickly ask you, you're also one of the authors on defining contracts. And I wanted to ask kind of how is that paper progressing? Do we think we're going to be getting
contracts back in the language after it was dropped from C++20? Right. So defining contract
is not going to progress anywhere
because it's a let's agree on definitions paper so it's a it's an fyi and not a design okay um
but i'm also a co-authored on the closure based syntax for contracts proposal i'm also the
co-author on the mvp for contracts proposal So those are probably better ones to cite.
The numbers are P2463 and P2388. So what happened there is that
contracts were not baked for C++20 and we took them out. And ever since, we've sort of been figuring out in the contract study group
what the minimum viable product looks like,
because we don't want to ship everything that anyone could possibly want in the P0.
We think that we have agreement on what semantic features
need to be there,
but it turns out that a lot of people
dislike the attribute-based
syntax that
the original C++20 proposal
used. And that's for various
reasons, not least
because it looks like attributes.
Contracts are this
really surprise pedantic design space
because we also put them into places that are shared with C, that is headers.
And so we actually need not to design just for C++.
We need to design something that C is going to want to use
in roughly the same fashion as well if we can.
And with C, it turns out that where the contract proposal currently puts those things is in the attribute space that applies to the function type and not to the function definition. And contracts don't really apply to the function type.
They apply to the function that you're defining.
And so they're in the wrong place if they're an attribute. There are worries that that will
cause confusion. I have other worries about that syntax, and it's just very constrained for what
else we want it to do. For instance, there's no nice way to really express a closure in that syntax.
And fundamentally, a contract checked in a post condition is a closure. You construct the closure
at function entry, and you run the predicate at function exit. And if you think about it that way,
a whole lot of things just get answered for you. So at that point like if you know it's a closure why don't just write it like a closure like a
lambda basically that has to return boolean so you can emit the return just like requires
expressions do um the return value has to go somewhere oh Oh, wait, we've got this thing called function arguments.
We can put the return expression
like the return value through there,
but we don't need to specify
its type because auto ref ref is
what you always want for that one.
So
we're kind of driven
towards the syntax for
abbreviated lambdas that
Barry Revzin proposed a while ago
and got rejected by EWG for lack of useful applications of the syntax.
Turns out we now have a useful application for that syntax.
And I hope that we get somewhere with that.
Unfortunately, the contract study group, for good reason,
is not exactly thrilled about waiting for EWG
to mull over abbreviated lambdas before we pass contracts.
So we have problems, basically.
Fortunately, with regards to C,
C is actually passing lambdas very soon, I believe.
They don't have closures, but they are inner functions
that you can just pass to Qsort or whatever they have, right?
And they use roughly the same syntax as in C++
because somebody looked at it and said, this seems good.
So if we pass something that looks like lambdas,
C might very well adopt it as well.
And that means that C and C++ can share contracts and headers.
And that would be wonderful.
That sounds great.
But yeah, that's kind of what we're hoping to achieve there.
It is not going to make C++ 23.
I was going to say, it sounds like the soonest that's going to show up is C++ 26.
And honestly, abbreviated lambdas coming because of contracts, that's
news to me.
I know you don't want to wait for it, but I would
absolutely love Barry's paper to be able to
be brought back to life and go through.
That's like a selling
point of contracts for me now.
Yeah,
well,
speak up. I think people
need some cajoling. All right. Well, G up. I think people need some cajoling.
All right.
Well, Gashper, it's been great having you on the show today.
Thank you so much for telling us about reducing this.
Well, this has been a pleasure.
Thanks for coming on.
Yeah.
See you some other day.
Thanks so much for listening in as we chat about C++.
We'd love to hear what you think of the podcast.
Please let us know if we're discussing the stuff you're interested in,
or if you have a suggestion for a topic, we'd love to hear what you think of the podcast. Please let us know if we're discussing the stuff you're interested in, or if you have a suggestion for a topic, we'd love to hear about that too.
You can email all your thoughts to feedback at cppcast.com.
We'd also appreciate if you can like CppCast on Facebook and follow CppCast on Twitter.
You can also follow me at Rob W. Irving and Jason at Lefticus on Twitter.
We'd also like to thank all our patrons who help support the show through Patreon.
If you'd like to support us on Patreon,
you can do so at patreon.com slash cppcast.
And of course, you can find all that info
and the show notes on the podcast website
at cppcast.com.
Theme music for this episode
was provided by podcastthemes.com.