CppCast - Expectations and Exceptions
Episode Date: August 2, 2018Rob and Jason are joined by Sy Brand to discuss his upcoming CppCon talks covering exceptions, value wrappers, debuggers and more. News The value of undefined behavior Qt Creator 4.7 released... Coroutines and Qt Links CppCon 2018: How to Write Well-Behaved Value Wrappers CppCon 2018: How C++ Debuggers Work CppCon 2018: What Could Possibly Go Wrong? A Tale of Expectations and Exceptions CppCon 2018: Overloading: The Bane of All Higher-Order Functions Sponsors Backtrace Patreon CppCast Patreon Hosts @robwirving @lefticus
Transcript
Discussion (0)
Episode 161 of CppCast with guest Simon Brand recorded July 26, 2018.
This episode of CppCast is sponsored by Backtrace, the turnkey debugging platform that helps you spend less time debugging and more time building.
Get to the root cause quickly with detailed information at your fingertips.
Start your free trial at backtrace.io slash cppcast. In this episode, we discuss undefined behavior and cute creator updates.
Then we talk to Simon Brand.
Simon gives us a preview of his upcoming CppCon
talks and much more. Welcome to episode 161 of CBPCast, the first podcast for C++ developers by C++ developers.
I'm your host, Rob Irving, joined by my co-host, Jason Turner.
Jason, how are you doing today?
I'm great, Rob. How are you doing?
I'm doing okay.
You know, every week I post the episodes
to the CBP subreddit,
and for the first time ever,
someone golded one of those submissions.
I've never had Reddit gold before.
Which one was it for, if I might ask?
I believe it was for the episode with Dimitri.
Interesting.
Yeah. So thank you to the kind listener
who gave me some reddit gold so you know i have absolutely no idea what that actually means no one
does no one does okay apparently it turns off ads when you're logged in so that's kind of nice
oh i thought that's what the ad block was for yeah well uh that's how every episode i like to read a piece of feedback um this week we got
an email from darstar he wrote hi uh first slash zeroth of all thank you for producing content i
enjoy so is cpp cast the first or the zeroth podcast for c++ developers by c++ developers thanks again
uh i think of those the same thing you know yeah you know that zeroth indexing is very important i
hate programming languages that use one as the first array element but i think of first and
zeroth kind of as an interchangeable thing as a programmer. That's interesting. I would be on board with changing the intro
so that we say we're the zeroth podcast.
However, it sounds a little bit like
we're saying that we're zeros,
which isn't generally a good content.
So I think we'll stick with first,
although we're both proponents of zero based indexing and
programming right yeah yeah i think we'll stick with first yeah okay uh well we'd love to hear
your thoughts about the show as well you can always reach out to us on facebook twitter or
email us at feedback at cpcast.com and don't forget to leave us a review on iTunes. Joining us today is Simon Brand.
Simon is a GPGPU toolchain developer at Codeplay Software in Edinburgh.
He turns into a metaprogramming fiend every full moon
when he can be found bringing compilers to their knees with template errors
and debating undefined behavior on the C++ Slack channel.
He co-organizes the Edinburgh C++ user group
and contributes to various programming standards bodies.
Outside of programming, he enjoys experimental films, homebrewing, and board games. organizes the Enber C++ user group and contributes to various programming standards bodies.
Outside of programming, he enjoys experimental films,
homebrewing, and board games.
Simon, welcome back to the show.
Hi, thanks very much.
All right, so recent homebrewing endeavors?
Not as recent as I would like, although I did just get 60 Swing Cat bottles
for free from a local pub,
and they're the proper good swing cap bottles.
That's not cheap, right?
Yeah, that would set you back like a good 60 pounds.
I guess that's like $90 at this stage or something.
Right.
Wow, yeah, that's a pretty good find.
No plans where you're going to put into those yet?
I think I might do an IPA or something soon, probably a double IPA.
We've got the weather for it in Scotland at the moment.
Sounds good.
Yeah, it's like hot there, right?
Yeah, it's Scotland's idea of a heat wave, which is like 25 degrees Celsius.
Wait a minute, now that's really not that hot.
Yeah, it's still enough to knock everyone out here if we're not used to this i'm i'm having to make sure i have my
conversion here yeah that's 77 rob yeah it's like yeah 90 to 100 every day here where i am
yeah okay well simon uh we got a couple news articles to discuss uh feel free to comment
on any of these then we'll start talking to you more about um your cvp con talks uh you got an
exciting year coming up at the conference right yep okay well the first one we have uh speaking
of undefined behavior is this article from chris wellens, The Value of Undefined Behavior.
Jason, you want to introduce this one?
Yeah, he goes through basically why we want undefined behavior in the language effectively
and how there's things that the compiler can optimize and whatever.
And the more we define, the less room there is for some of this.
One thing you pointed out,
that part of it is to make things easier for implementers
which i'm not sure if i was aware of well yeah and part of it is if you over specify the language
then you make it uh almost impossible to run c++ on certain you know types of hardware or whatever
yeah or they might have to introduce additional checks or extra instructions to make sure that they're conforming
to what the standard says even though like their default behavior might be okay right so yeah
definitely an interesting article we're always talking about having how to avoid undefined
behavior but it's interesting reading these articles talking about the occasional benefits of
it yeah i've had conversations with people and i don't think it's come up on the podcast but i could be wrong the
notion of making a compiler that uh intentionally is uh malevolent i guess in the face of undefined
behavior just to like punish you for using undefined behavior. It could be a fun experiment, I guess,
but no one's doing that that I'm aware of.
That would be interesting, yeah.
Okay.
I have thought about doing something like that,
like just modifying clang so that some check
actually does delete your hard drive or something.
That would be great.
Calls your, i don't know family members that you haven't talked to in a while or something yeah
okay uh next one we have is uh qt creator 4.7 was released and i guess the big change here
is that they are officially switching over to using Clang instead of their own internal C++ model.
Yes, that did seem to be the big item.
Yeah, it seems like a good move.
It makes it a lot easier for them to work with the new versions of the standard
and new features which are coming in,
because there's so much stuff now getting into C++
that it must be hard for all of these individual tools to keep up.
So centralizing it somewhat seems like a good idea.
Okay, so at the risk of maybe playing devil's advocate here or something um do we think that
so all right so clang is very very good about sticking to the c++ standard i will preface with
that but do we think we're at a risk of like whatever clang it does implement becoming like
the de facto dialect of c++ because we're using these tools in so many places now?
I guess it's like, what features or what areas would we be relying on the implementation
defined behavior of Clang?
Like, are there any very important parts which would be doing that?
Especially when we're mostly thinking about these tools and static analysis and things like that,
rather than a lot of these tools aren't so much focused on the dynamic behavior.
It's mostly about diagnosis and giving information about your types and things like that.
So I can think off the top of my head, big issues issues which we'd be relying on for things like that.
The only thing I can think that might plausibly come up
is Clang does strictly evaluate parameters left to right,
and neither GCC or MSVC do.
Yeah, I don't know.
It doesn't seem like it's a huge concern for the community to be kind of
rallying around a certain tool this way.
Yeah, I just thought I'd ask.
In my experience, C++ programmers
are very quick to point out if,
oh, actually, this thing is implementation-defined
or you're relying on some aspect of this compiler.
Yeah, as a community community we're not very shy about pointing these things out in my experience right that's very true
okay then last article we have today also qt related um this is the qt and coroutines ts
and uh you know, interesting example,
I think we've talked before about signals and slots
being a really common way of hooking up your QT events.
And this is an example of how you could do this
using coroutines, and it is much, much cleaner.
You know, to just say,
await for some click event and do this, and
once you have done that twice,
you can go about your business.
Instead of having to track
a bunch of state within your slot
event handlers.
I thought this would be an interesting one to cover
because I feel like with all the conversation about
coroutines, for myself
personally, I'm like, I just don't
really know how this would affect my real
world code and i know you have more experience with coroutine like things because of your c
sharp experience rob but i don't i've spent a lot of time in the c++ world yeah this is not really
a pattern i've seen too much in C Sharp with kind of making a task await
on an event, but
it's something I might try out.
See how well it works in C Sharp.
That'd be cool.
How well it might work in Curve Routines.
How about you, Simon?
I really like this approach.
I mean, so much of asynchronous
programming or this kind of event-driven
programming, the actual control flow and trying to trace everything that's happening
becomes kind of inside-out, and this puts it back into the right order.
So it looks like straight-line code,
and all of the actual event-driven stuff is just kind of hidden underneath the covers.
So yeah,
it's very nice.
Yeah.
Okay.
Well,
Simon,
as we mentioned before,
you're going to be at CppCon again this year and you signed up to do four
talks.
Is that right?
Yeah,
this is actually my first year at CppCon.
So,
you know,
I'm starting,
starting easily.
Well,
you've spoken multiple times at Meeting C++, right?
I gave two talks at Meeting C++, but only been there once.
Okay, two talks in the same year.
Any other conferences, your local users group you're involved with?
Yeah, users group.
I spoke at C++ Russia this year and Embo++ as well.
Oh, okay.
So you're highly experienced at this point.
All right.
So what was the motivation for submitting four talks?
Let's start there.
Yeah.
Well, it was the kind of thing where it was the first time when I'd submitted to CppCon
and I really wanted to go.
So it's like, well, if i if i submit two talks
then i've got a fairly good chance of getting in i was like and that's the kind of thing you know
you're thinking oh well if two talks isn't enough maybe i should submit a third one and then in
trying to come up with a third one i was like oh i have another idea as well so i ended up just
submitting four talks and i was just like this will will be fine as long as all four talks aren't accepted. And then, of course, all four talks are accepted.
So are they all fresh ideas or anything that you've presented previously?
One of them is one that I gave at a meeting C++. The others are all new,
although some of them are based off of blog posts I've done and things like that.
Okay.
Did you consider asking John Kolb and the CPCon committee,
like, hey, could I maybe back out of one or two of these?
Yeah, I did think about it,
but then I also thought it would be an interesting challenge
and not one which I'd have many opportunities to try again.
Even in the future, if I submit four talks again,
the chances of all four of them getting accepted again
would probably be quite low.
So I thought I may as well give it a try and see how it goes.
Well, if these four go well,
then in the future, the next four have a higher probability of getting accepted, just for the record.
What have I signed myself up to?
I think, since I've been speaking at conferences for a few years now, I would like to point out for our listeners who are thinking,
Hey, I thought about submitting a talk to a conference, but I'm never going to do that because I don't want to get stuck in this world of doing, you know, 20 talks. Uh, you are a volunteer at the conference.
Effectively you are allowed to back out of talks. So there's no way that they can require you to do
all these talks. And John, you know, might be casual, uh, quietly disagreeing when he's listening to this or something, but just for the record, so don't, don't take Simon's experience experience and be
afraid to submit talks in the future to our other listeners. Okay. Now that that's out of the way,
let's talk about what your talks actually are. Sure. Um, so as I said, one of them is one I gave at
Meeting C++
last year, so that's the
How C++ Debuggers Work talk.
Okay. So it's all about
I did a lot of work
on debuggers in the
first few years I was at Codeplay,
and there are very
few resources about
how debuggers actually work online and how you might write one.
So I wrote a 10-part blog post series, and we talked about this last time I was on, about a year ago,
and then gave the talk at Meeting C++, which was kind of just putting a lot of that stuff into talk form.
Not so much like, how do you write one, but how does it all work?
And so this is going to be essentially the same as meeting C++, but I'm gonna...
that one was a little bit more generic, like it could have applied to pretty much any native debugger.
For this version I'm going to try and make it a bit more C++ focused to talk about how templates interact with debuggers,
how name mangling is actually exposed in the debug information,
things like that.
It might also be interesting to look at how
debuggers would interact with things like contracts
or coroutines even.
That could definitely be interesting.
Yeah, because I'm not sure how
much
debugger support was
actually considered or discussed during
the standardization for these features.
It would be interesting to at least consider.
Okay.
So is it the same session
length, one hour?
Yeah, one hour session.
So new material. Okay, so is it the same session length, one hour at meeting C++? Yeah, one hour session.
Okay.
So new material.
So if someone saw your meeting C++ session,
should they come to your CppCon session?
Yeah, I'm going to try and make it as it will be expanded.
I'm going to try and tighten up some bits,
make it more of a kind of story of, because the meeting C++ one was
like, okay, here's a debugger feature, here's how it works, here's another debugger feature,
here's how it works, and so on and so forth. So I thought it would be better to be like, okay,
say I have this problem, and I'm going to go through a bunch of debugger features, which
will actually help me solve this problem.
And here's how all of these work and try and draw more of a nice path through all the features
other than just chunking them up and describing them one by one.
I wanted to interrupt this discussion for just a moment to bring you a word from our sponsors.
Backtrace is a debugging platform that improves software quality, reliability, and support by bringing deep introspection and automation throughout the software error lifecycle.
Spend less time debugging and reduce your mean time to resolution by using the first and only platform to combine symbolic debugging, error aggregation, and state analysis.
At the time of error, Bactres jumps into action,
capturing detailed dumps of application and environmental state. Bactres then performs automated analysis on process memory and executable code to classify errors and highlight important
signals such as heap corruption, malware, and much more. This data is aggregated and archived
in a centralized object store, providing your team a single system to investigate errors across
your environments.
Join industry leaders like Fastly,
Message Systems, and AppNexus
that use Backtrace to modernize
their debugging infrastructure.
It's free to try, minutes to set up,
fully featured with no commitment necessary.
Check them out at backtrace.io
slash cppcast.
Okay, so your first talk
is on debuggers.
What is going to be the second one um so another
talk is um how to write well-behaved value wrappers um so this is based a lot on um my
implementations of std expected and optional but it just as equally applies to things like tuple and variant and pair and pretty much anything which is a generic type
which wants to act like a value and expose behavior
which is consistent with the values it's wrapping.
So the talk's going to go over a bunch of techniques
for making these types behave well and to be
performant because there are things like um trivially copyability trivial copyability um
which you have to actually work a little bit hard to expose properly in the in the value wrapper
so for for example the um the original version of libstdc++'s optional did not propagate the trivially copyability of the underlying object.
So if you were passing these over function boundaries, like as arguments or return values,
then if you're using the sysv ABI, then they're going to be passed on the stack
just because that's how the ABI is specified.
So if you want it to be
passed in registers, like if this is just an optional
int, you want that to be passed in
registers, so you have to
make sure that the type is trivially copyable.
So there are techniques
you can use to do that, like
inherit from
some private base class class which conditionally
um defines or defaults those special member functions and it gets a little bit hairy and
is kind of non-obvious when you're first looking at it but it it does actually work i found that
an interesting exercise and trying to maintain trivial
destructibility and the same kind of...
Yeah, I talk about that as well.
It's very much the same kind of
issue. The same goes with
propagating the deletion of
special member functions.
I'll talk about things like ref-qualified
member functions for
propagating the value category
of the object you're calling something on um and yeah and for all of these things i'll also be looking at how
current proposals or um things which are coming in c++ 20 might um help make this a little bit
easier because currently a lot of these techniques are a little bit esoteric
and
there are a lot of new features
like the space ship operator
for comparisons and
concepts and
maybe deducing this
which would help massively
in a lot of these things
so I'll look at the performance aspects
and look at some assembly code and look at the future
and try and explore lots of different avenues
within this kind of niche.
All right, so I am slightly confused
by the name value types,
because in my head, when you started to say that,
I'm thinking of like strongly typed value wrappers,
like Jonathan Mueller likes to blog about and stuff, I think, where you're talking like,
it's something that wraps an int, and then you have all of your normal operations on it,
but it gives you a strongly typed wrapper. And so if I'm understanding correctly,
you're not talking about that kind of thing.
Well, even for that kind of thing, some of these concepts still apply. You still want to expose all of the comparison operators and things like that, and I'll talk about those. And so there are still aspects which will apply to those kind of strong types um kind of style as well okay now i am curious also for actually
demonstrating these techniques uh finding a compiler right now that implements the
spaceship operator and contracts and or excuse me concepts and some of the other things you've
talked about not trivial yeah so the the assembly stuff will mostly be looking at
what happens if you don't do this.
So if you don't correctly propagate trivial destructibility,
like you mentioned,
and then you have a vector of these things,
then the code generated for the destruction of the vector is pretty big.
But if you propagate it properly, then it becomes essentially a no-op.
So I'll compare and contrast.
Here's why you should do this thing, because it impacts the performance,
and you can actually see how it impacts the performance by looking at the assembly.
And maybe I'll have some quick benchmarks or something
as well.
Okay.
And how about one of the other ones?
So one of them is going to be
a half session,
so a 30-minute talk
about...
You should have backed out of the other three and just
kept the 30 minutes
just kidding and that one's going to be about how um function overloading and function templates
interact with higher order functions and how there's kind of a fundamental hole in support
for these things in c++ in the moment.
So if you have a high-order function just like anything in the algorithm header,
and you try and pass a function template to it,
then you can't just pass the name. You have to explicitly choose a specialization,
or you have to wrap it up in a lambda.
It's the same for overloading. You have to static cast it, or wrap it up in a lambda again,
or make a...
What do they call them? The customization point objects,
like the ranges style things, which just hide everything in an
explicitly defined function object.
And if you don't
do any of these things, then
you get compiler errors.
And if you do do these things, then your code
looks ugly.
So I'm going to explore
some techniques for
doing it now.
Just like defining a macro which builds a lambda for you
which correctly perfect for his arguments
and propagates noexcept and is SFNA-friendly
and all of these things.
Because you don't want to be doing that by hand
every single time you want to call a high-order function.
And then I'll look at some approaches which the standard could take
to make this easier. So there were a few proposals
which had been discussed at recent meetings, but unfortunately
got rejected. And then there's one which is
currently being written, and
we'll see how that goes
but yeah so I'm going to look at the
current state of things which is bad
really bad and look at
how we might try and fix it
I'm curious
if you know if any
of these proposals tie into any
of the things that have been talked about for reflection
but I mean can you reflect on
a template function since a
function template doesn't
actually exist, really?
Yeah.
I don't think I've actually
looked at that. That might be
an interesting avenue to consider.
Because I guess you...
I guess it would have a similar issue
unless it had...
Reflexper, it's called. unless it had unless it reflects where it's called unless it had like
explicit support for um overload sets given a name then uh you would have a similar issue where
if you're wanting to reflect on something you have to say exactly what you're wanting to reflect on
right so i am though, if you can
give us a preview as to how any of these
proposals that you are already planning to talk
about would work in this kind
of situation. Yeah, so the
one which is
currently still
being written,
it hasn't been posted
in the mailings yet, but
the author said I could mention it here.
So Barry Revzin and Andrew Sutton
are working on a proposal for a Stid Overload set.
So the idea is this is a kind of magic type,
and you can pass it a name,
and it will deduce a type which essentially wraps all of these overloads or function template special the higher order function so that when you pass name as the function argument then it
gets deduced and you don't have to write any additional magic at the call site.
But additionally if you have a function which does not have a std overload
set overload then you could construct one automatically and just pass it through.
And if the high-order function takes a std function
or just a deduced template parameter, then it should still work.
To make sure I'm clear on this,
this would truly be magic. It would be impossible to implement this as a library
function today. Yeah, absolutely. It would be impossible to implement this as a library function today.
Yeah, absolutely. It'd have to have compiler
support.
Okay. It also sounds like it could be
handy for creating visitors.
Yeah, I guess it would be...
Yeah, because you'd have exactly the same
problem if you have an overload
set which you want to pass as a visitor
then you'd have to wrap up in the lambda
so yeah, we'd
definitely go to solving that issue
Yeah
Yeah, because there'd been a few proposals
to do
to solve the same issue before
one of which Andrew Sutton wrote
and it was like a
kind of
if the
if we think we can make this call work, then the compiler will just work out what needs to be done.
And it will all be done under the hood without the programmer having to do anything.
And it turned out that there were some kind of fundamental issues with that.
And then Mikhail Domniak, I don't know how to pronounce his name.
I think it's close.
He had a proposal for a lift operator,
which is just like an open square brace, closed square brace,
which you put before a name,
and that would essentially lift that name into an overload set.
So it was doing something kind of similar to the std overload set,
but with some special syntax,
and it wasn't something that you could put
in a function interface.
So what is the actual result of this?
Is it a function object?
Is it a lambda kind of thing,
like something we can reason about,
or is it something we're not allowed to know about?
So I think currently it's uh it kind of depends on
what you are passing so if you like just create a std overload set out of a function pointer
then i think i'd have to check again but i think that would just result in a function pointer
that would make sense no reason to add any overhead. Yeah, exactly.
But if you pass the name of an overload function,
then it would have to lift it into a lambda
type thing.
That sounds pretty cool.
Is there one more talk we haven't talked about yet?
Yes.
So this one...
Oh, what did we end up calling it?
It's a,
a joint talk that I'm giving with,
uh,
with Phil Nash and we're going to,
it's harder to back out of the joint ones.
Yes.
Yeah,
exactly.
Uh,
but it's going to be on,
um,
error handling in,
in C++.
Uh,
so it's going to focus a lot on,
um,
it's going to go all the way from error codes to exceptions
through to std expected
and into the
static exceptions
proposal which Herb Sutter
has written
it's called
what could possibly go wrong
so yeah
we're going to be
evaluating a lot of these different approaches
and it's going to be
quite similar to
I don't know if you've seen Phil Nash's talks
he gave one at
C++ Now
entitled optional
is not a failure
so it's going to be quite similar to that
there's a few extra things which we want
to cover in this talk, which will replace some of the content for that one. But it's going to be
kind of a similar style, just evaluating different approaches. One of the things which I
want to talk about is, did both of you read the static exceptions proposal?
Yes, I did.
Yeah, it's been a while, but yes.
Maybe I can summarize it for
listeners who haven't read it.
So the idea is that
the current
C++ exceptions
model is
kind of against the core
C++ principle of you don't pay for what you don't use, and that
if you enable exceptions, then extra code is going to be generated in order to actually make sure that
the rules in the standard are followed for how these things are propagated and caught and things
like that. So if you just enable them, then you're paying for something.
And even if you're using them
and you actually want exceptions
and you want to throw them and you want to catch them,
then they're still overhead associated
because you can throw an object of any type
and that might get caught immediately or it might get caught
way back up the call stack. So the compiler has to do a lot of work and add a lot of extra
instrumentation into your code in order to make sure that this all works, no matter what type
you throw and no matter how far up the call stack it's propagated. So the idea of the static
exceptions proposal is
that you
say, I'm a function
and I
could produce an exception
and it will be of this type.
So you statically know
what type you're going to be throwing.
And that means that not only
do you know the size of the type,
so you don't need to dynamically allocate these things,
but you can also just return it
as if you were returning a normal return value.
So it kind of translates your function.
If I have a function which returns an int,
and I say I can
throw an object
of type std error, which will be
a special thing,
then it kind of translates your function
into something which returns
either an int or a std
error. So it's kind of like
std expected,
but built into the language.
Right.
So that's the kind of
overview of
how it works.
And in the proposal
there's a bunch of optional stuff
which is kind of related
to the proposal
and would augment it somewhat
that isn't part of the core functionality.
So there's things like
operator try,
which Nell Douglas had a
standalone proposal for as well.
But the idea of operator try is
you
put it before
a call to some function which could
throw, and then if it
does throw, then you essentially early exit
and uh it lets you write all this stuff in in a straight line kind of like coroutines in a lot
of ways you're not having to pepper about um a lot of additional boilerplate you're you're kind of
just um propagating things things as you get them
but the thing which I think is really interesting
about
having to manually
specify that I want to propagate this
error backwards
is that if you don't do that you get a compiler error
so
if I call a function
which could throw
and I don't put a try before it, then the compiler is going to tell me that I've forgotten something.
Which means that I need to program more defensively, I need to always be thinking about, okay, well I'm going to call this function, and I need to think about what I do in the error case.
Maybe that's just I propagate the error backups call stack.
Maybe it's I do some manual handling,
but I always have to write some code in order to handle it, even if it's just writing try before the call.
So I think that's a really interesting element to the whole discussion,
especially because I i did some
some programming in rust and uh writing a parser in rust i was always thinking about um those edge
cases of uh okay well i'm at this point in parsing and i get some unexpected token how am i going to
deal with that and i was always thinking about how this is going to work, so when I actually got a finished parser it was
very robust because I thought about all the edge cases. Whereas with C++ it's
a little bit, well actually it's a lot easier to just kind of say okay well
I'll program for the the common case and oh yeah if this error could happen so
I'll fix it here and oh this error could happen, but you're not forced by your compiler to think about these things. So I think that's quite valuable. of it because having used java back in the early days and having to always account for all the
different types of exceptions that could happen and either try and catch or repropagate and you're
and now i'm assuming um this isn't going to try to change the rules again where we have to
explicitly specify all of the different types of exceptions that could possibly happen or something
like in the java land yes i Yes, I mean, with the static
exceptions, you can only throw
one type of error.
Okay.
And that might be an error code
which aggregates a lot of
possible runtime errors.
So it could be a type which
at runtime
could say, oh, I ran out of memory
or a file not found or any of these kind of system-level errors.
Or I guess if you had multiple errors which could occur,
you could throw something like a std variant, I guess.
Yeah.
I'm not sure if that's the best option,
but then you end up visiting on something you catch.
Yeah, it might work.
Should work.
So you said you were involved in the standards committees.
Did you attend Rapperswell?
No, so the C++ standards stuff, I haven't done a whole lot of work for.
I've written
a handful of proposals and
co-authored a few of them.
Most of my standards work was on
HSA,
which is a heterogeneous
systems architecture.
It was like a very low level
hardware description
and intermediate
representation and
runtime for
heterogeneous systems like if you have
a CPU and a GPU and
DSP and some other
accelerators so it was something which was
pushed mostly by AMD and
Qualcomm, Samsung,
ARM, people like this.
So that's where I did most of my standard stuff.
Okay.
But yeah, I have a couple of papers
which are going through
the standards at the moment.
One of which is adding
monadic extensions to std optional.
So what does that mean?
Yeah, I guess I used the M word, didn't I?
You used the M word.
Now you have to explain exactly what a monad is on air.
You're legally required to do that.
Well, arrest me because I'm not going to do that.
But I will explain what it means for optional
because that's a lot more uh useful to everyone i think um so what essentially means is um if you're
using std optional in its current state uh and you have a lot of operations which will return an
optional then you would essentially have to do something like
call a function, check if it failed.
Call the next function, check if that failed.
Call the next function, check if that one failed.
For some definition of failure, but you know what I mean.
So essentially all of your business logic is interrupted
by you having to handle this context of whether I got a value or not.
And that's not great. You end up trying to read this code, it's not obvious what the intention
is because there's so many checks. So what you really want is something like, say, okay,
I have this pipeline of operations which I want to execute on this data.
If at any point any of these fail,
or if at any point any of these don't return a value,
then I just want to exit out
and not do the rest of the pipeline.
And that's what the monadic style of programming gives you.
You push the handling of the context into the implementation of the type, rather than having to do it manually.
That's the essence of it.
So what does this actually look like? Is it like a.then,.then,.then kind of thing? Yeah, essentially. The proposal has three
member functions
which it adds to optional.
One of them is map,
where you essentially take the
value out of the optional, if there is one,
you apply some
transformation, and
then you put it back into an optional.
But if there wasn't value,
then you just do nothing.
It's a no-up.
So that's map.
It's kind of like a std transform, essentially.
If you have an empty vector
and you do a std transform on it,
then you do nothing.
If you have a vector with one element,
then you're going to take that element,
call a function,
and put it back in a vector.
It's essentially the same thing.
So that's one member function.
The next one is and then, which is similar,
but it's for composing operations which themselves return optionals.
So this is the kind of case where you have a bunch of operations which themselves could produce no value, and you want to push all of that context aside.
So you just say, I want to do this and this and this and this and this, and if at any point one of those returns null opt, then the whole expression just stops evaluating those additional calls.
I mean, the calls are evaluated,
but the function you pass
isn't called.
And the final one is
or else,
which is just, if there is no
value stored, then do this thing.
And that's quite useful
for, if you have
interface which uses exceptions,
then you can
use this to
get out of your
monadic style of programming
and into exceptions land.
So you could say something like
do these operations
or else throw an exception.
So you can kind of implement,
your implementation could be done in this monadic style
and your interface could still be specified
using dynamic exceptions.
So if you have this chain of if-then,
or whatever it was called,
and then it fails halfway through.
Do you get any way of knowing where it failed?
Um, not with optional.
Um, with expected, uh, because it, for people who don't know,
expected is essentially, it's like optional, but it gives you, uh, um,
a kind of error value.
So either I have the value requested or I have something which tells you why I didn't get the value.
So expected would give you that additional information.
With optional, you would just know that I didn't get a value at some point in this pipeline.
And maybe that's okay for your domain, maybe it's not, and you use expected instead.
And expected is going to make it into C++20, hopefully.
Right.
But it's also implementable previously, so I have a version on my github which is uh usable in c++ 11
so with these four talks debuggers value types higher order functions and error handling do you
are you hoping to give them in a particular order? Are we going to see like a common thread through any of them?
Will one refer back to another?
I can see some places where you might do this.
Yeah.
So the,
um,
the one on value types and the one on error handling,
uh,
kind of interact a bit because a lot of their handling facilities,
which we'll talk about,
uh,
when you're implementing them, you have to think about a lot of these
concerns. And the
overloading one will also
play into that a bit, because
if you have something like a
monadic interface
or something with
higher-order functions, then
you need to think about these
considerations.
So those three talks are kind of related,
and then the debugger one is off to the side a bit.
I probably won't tie them together too much
because I doubt many people will want to go to all four of my talks.
You'll probably get enough of me after the first one or two.
But yeah. you'll probably get enough of me after the first one or two but yeah that's what the online recording support
afterwards
okay well it's been great having you on the show again
today Simon is there anything else you want to talk about before we let you go
I guess I could briefly talk about since last
year I've also been involved in setting up the HashInclude
community
which is a
diversity community and initiative
for C++ programmers
trying to get
we have a Discord server which
has a public
invitation so people can jump on
there and just come and talk
about C++ and uh how we
can kind of improve our spaces to be more um welcoming and inclusive of minority groups and
people who aren't so well represented in in c++ communities
and how is the effort going so far yeah i mean we've got uh i think we hit maybe 400 people
on our discord just the other day um so that's been cool and we're we're discussing ways in which
we can uh have a presence at conferences and help people out and maybe run some events like uh we're talking about maybe
running some mock interviews or something so if you're a junior programmer and you don't have much
experience in in interviewing situations then you could sit down with someone and um and try out and
get some feedback on on how you interview and it's not so much of a high stakes
environment.
So we thought that might help people.
That does sound like that could
be very helpful for a lot of people actually.
Okay. Well it's been great having you
on the show again today Simon. Yeah, thanks very much for having me.
Thanks for coming.
Thanks so much for
listening in as we chat about C++
I'd love to hear what you think of the podcast
please let me know if we're discussing the stuff you're interested in
or if you have a suggestion for a topic I'd love to hear about that too
you can email all your thoughts to feedback at cppcast.com
I'd also appreciate if you like CppCast on Facebook
and follow CppCast on Twitter
you can also follow me at Rob W Irving and follow CppCast on Twitter. You can also follow me at Rob W. Irving
and Jason at Leftkiss on Twitter. 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 is provided by podcastthemes.com.