CppCast - C++ Object Model
Episode Date: December 21, 2017Rob and Jason are joined by Nicole Mazzuca to talk about the C++ Object Model, and some of the differences between Rust and C++. Nicole is someone who's thought a bit too much about object mod...els and error handling. She started in C, moved to Rust, and then fell into C++ a year ago. She also loves coffee, and latte art. News Meson 0.44.0 is out C++Now 2018 Call for submissions MSVC code optimizer improvements in Visual Studio 2017 version 15.5 and 15.3 Broken warnings theory Nicole Mazzuca @ubsanitizer Nicole Mazzuca's GitHub Links CppCon 2017: Nicole Mazzuca "Values, Objects, and References, oh my: The C++ Object Model, and Why it Matters to You" Sponsors Undo Audible Hosts @robwirving @lefticus
Transcript
Discussion (0)
Episode 131 of CppCast with guest Nicole Mazzucca recorded December 14th, 2017.
This episode of CppCast is sponsored by Undo.
Debugging C++ is hard, which is why Undo's technology is proven to reduce debugging time by up to two-thirds.
Memory corruptions, resource leaks, race conditions, and logic errors can now be fixed quickly and easily.
So visit undo.io to find out how its next-generation debugging technology
can help you find and fix your bugs in minutes, not weeks.
And by Audible.
Get a free audiobook download and a 30-day free trial at audibletrial.com.
Over 180,000 titles to choose from for your iPhone, Android, Kindle, or MP3 player.
In this episode, we talk about some Visual Studio updates to help manage warnings.
Then we talk to Nicole Mazzucca.
Nicole talks to us about 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 your host, Rob Irving, joined by my co-host, Jason Turner. Jason, how are you doing today?
I'm doing okay, Rob.
Through the magic of radio here, I guess, this is being recorded one day after the last episode.
Indeed, we're doing time travel again.
So I got a new tooth.
Nice.
Because we did mention that.
And I think I'll maybe be a little bit more alert today hopefully
that's good but this is we're doing time traveling here not time travel debugging
mind you right just time traveling of the episode because i'm heading off to poland
to do some training there um on saturday awesome awesome so uh can you tell us what company you're going to? Who are you going to be seeing in Poland?
I don't know. I didn't discuss with them if they want me advertising that or not.
But it's a consultancy that's in Wroclaw.
And it looks like it'll be a beautiful time of the year.
They're expecting some snow and they've got a wonderful Christmas market downtown.
I'm hoping to see that.
Very nice. That should be fun. know and they've got a wonderful christmas market downtown i'm hoping very nice yes very nice that
should be fun uh i also am wishing we could do some real-time traveling right now because i'm
very excited for the star wars movie coming out this friday isn't that oh i thought that was
tonight for some reason uh i think yeah the midnight midnight showings yeah i might try to
find one of those yeah you've got kids I'm sure they would love to go.
Yeah, I'll have to do that.
Well, at the top of our episode, I'd like to read a piece of feedback.
This week we got an email from Nikolai Zapoklov,
and he writes in,
Hello, Rob and Jason.
Your show is really useful for new developers
to introduce in the context of developing software and C++ especially.
Thank you.
Could you touch the topic about wrong using design patterns?
I heard a lot of developers very often abuse using design patterns.
Maybe someone can share his experience about restrictions
and using design patterns and when they stop working.
We haven't really done any episodes on design patterns.
Are you a design patterns guy?
I wouldn't say i'm a design patterns
guy i know you i feel like i know almost nothing about them yeah i mean and and i've seen
discussions where people say well why doesn't the standard library have templates for the various
design patterns that are the most common popular and the responses seem to be something along the
lines of uh you know the design pattern should be
a guideline not something you try to shoehorn all of your designs into basically right but i don't
know i it's actually it's been on my to-do list for literally over a decade to make sure i understand
better yeah yes i should probably get to that to-do item at some point.
Yeah, I could definitely see doing an episode about it too.
Could we get someone on who is very familiar with multiple design patterns
and can speak to, you know, this is good for that, this is not.
Do you know who the Gang of Four is?
I'm familiar with the book, yeah.
Yeah.
Well, maybe we should try to get one of those guys on here.
Yeah, that'd be good. That book, yeah. Yeah. Well, maybe we should try to get one of those guys on here. Yeah, that'd be good.
That'd be crazy.
Yeah.
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 cpcast.com.
And don't forget to leave us a review on iTunes.
Joining us today is Nicole Mazzucca.
Nicole is someone who's thought a bit too much about object models and error handling
she started in c moved to rust and then fell into c++ a year ago she also loves coffee and coffee
and latte art nicole welcome to the show hello what do you think of design patterns nicole
uh i have not ever really thought about them to to be quite honest. I thought with that intro of object models, well, but that's object modeling versus object memory object models, right?
Right, yeah. It's more like objects have value semantics as opposed to objects are patterns, I guess.
Right.
Like, the only thing I can even think of that's
anything close to a pattern is
Sphenae or something.
Yeah, that's really not
one of the
design patterns, I don't think.
Hey, it's very
important to design your classes to be Sphenae
friendly. Yes.
So, do you want to talk about this love of coffee art at all
uh i mean it's just i like making latte art it's it's a fun thing to do on coffee and people get
happy when i i'm a barista in my everyday life. Right, that's an important note, I think, here, yes. Ah, and, I don't know, people tend to enjoy it when I make latte art,
because latte art's awesome.
Some of the pictures I've seen on the internet are, like, nuts.
Like, what kind of things do you do?
I am not that good.
You're not, like, make a Darth Vader?
No, I cannot make a Darth Vader.
I've not been practicing for 10 or 20 years.
I mostly do, like, hearts and, like, leaves and stuff like that.
You know, just basic stuff.
Oh, that's cool.
Yeah.
Okay, well, Nicole, we've got a couple news articles to discuss.
Feel free to comment on any of these,
and then we'll start talking more about your love of the object model, okay?
Okay. Okay. So first the Nissan build system release 0.44.0 is out.
Jason,
anything really big to share with this one?
You know,
I don't know if there's anything of particular stands out,
but I think it was just important to mention it because we've had,
we've talked about Nissan on here before.
We haven't done a dedicated episode yet though i don't believe right i will have to look i don't think we have no i don't think we have we've talked about cmake a whole lot more than
we talked about some of the other build systems like nissan did talk about Nissan. There we go. You're right. You're right.
Episode 38.
It was a long time ago.
With the author of Nissan, yes,
which is why I was thinking we should have this up here.
But anyhow.
Yeah.
Okay.
Are you involved in build systems at all, Nicole?
I've thought a lot about their design.
And me and Izzy Muerte
were going to do some work
on a build system, and we've kind of
started a little bit.
A module-friendly
build system, perhaps?
Yeah.
That's something that's really important to me.
I don't think it's going to be in the
initial release, but
definitely important to look up modules right okay yeah uh next up we got a c++ now
2018 call for submissions yes and this one uh what is the dates on these jason
um oh that's terrible that link that i have on there didn't say the exact date And what is the dates on these, Jason?
Oh, that's terrible.
That link that I have on there doesn't say the exact date.
It's March, I believe.
It says submissions due on January 24th. Oh, January 24th.
Okay.
And decisions get sent out February 26th.
Program will go online March 18th.
So I have made my submission.
You're already in?
Okay.
Yes.
This year I am attempting to give one talk.
That's good. Just one talk.
Didn't you send in three last year?
Yes.
It is my goal to go to this conference and give one talk.
We'll see what happens.
The risk is you make one submission and it doesn't get accepted, right?
Then you have to decide what you're doing.
I think it's a lot better than sending in three submissions, though,
and getting two accepted and not being able to handle it.
Or getting all three accepted.
Hey, I think I've always...
Oh, I know, I know.
Are you planning to submit anything, either one of you?
I don't have any plans right now to submit anything.
How about you, Nicole you i don't have any plans right now to submit anything how about you nicole i don't i don't either uh i don't really have anything that i want to say right now i've mostly been using ocamel recently and not c++ so i don't have a lot of opinions
about c++ right now okay okay uh next we got uh two articles from the Visual C++ blog.
This first one is code optimizer improvements in Visual Studio 2017 versions 15.5 and 15.3.
So it looks like they made a ton of improvements between 2017 and the 2015 update 3.
Yes.
Yeah. the 2015 update 3. Yes. And I think more important than
the fact that Visual Studio now has
these optimization features
is as a C++ developer,
reading this article to understand
what kinds of optimizations
the compiler writers are thinking about.
And there's some technical stuff in here,
lots of assembly examples,
how conditional moves can help the code, for example.
And then things like CSE,
common sub-expression elimination and stuff.
And SSA is mentioned here,
static single assignment form,
which is also important to understanding how optimizers work.
I feel like I have a passing familiarity of these things,
but for anyone who's interested, they should read this.
Yeah, it's definitely worth scrolling through the article
and seeing kind of how the optimizer is working
with some of these improvements.
Yeah.
The loop unrolling is really interesting in my opinion um how how they
do loop unrolling and then like are able to optimize based on the loop unrolling it
feels very similar to like the stuff that you can do if you uh inline um yeah so it's just like
i don't know i like that it's cool yeah, I like that. It's cool. cache, if you will, by making unrolling everything outweigh the benefit of doing the unrolling,
since modern CPUs are really good at jumping and keeping hot code and path in the cache.
But this kind of example like they have, where you've got a known size, and they know that they
can exactly unroll it to four things, I feel like that has to be a clear win. And then the
optimizations that they can perform after that,
like you were saying, is pretty cool.
I feel like for real programs,
there are a lot of little loops like this,
but it would be...
I don't know, I'm just thinking about loops with 128 or something like that.
And at that point, you're probably unrolling it eight times and then looping,
as opposed to unrolling it 128 times,
which that's an insane number and will not keep you in iCache.
Right.
The partial unrolling that some of them will do.
And I've also noticed with this kind of loop,
like if there's a known size or something with partial or partial or full
unrolling,
and these were like,
you're working the,
this,
the unrolling gives the vectorizer the chance to work and potentially use
SSE instructions also.
Yeah,
exactly.
Okay.
And then the other article we have from the visual c++ blog is the broken
warnings theory and the the main thing that they're announcing here is these new external
compiler switch groups which will allow you to basically disable or change the warning level
for external headers and this is something that i think will be really useful for getting a build with clean
compiling without warnings or with all your warnings turned on, not having to worry about
all these external headers.
Did you notice in the statistics at the top of this article, they say 27 respondents to
their survey, 27%, excuse me, of the respondents to their survey,
compile Visual C++ applications with dash W all.
Yeah.
And I find this fascinating.
I mean, that's what I do.
Like, I do dash W all,
and then I just turn off specific warnings.
In Visual Studio?
In Visual Studio and in Clang, I use W everything and turn off specific warnings. I Visual Studio? In Visual Studio and in Clang,
I use W everything and turn off specific warnings.
I have found, okay,
so there's a philosophical difference here, right?
Because Clang and GCC exclude themselves
from warning messages.
Excuse me, the standard library excludes itself
from warnings.
It's treated as a system header by default.
In Visual Studio, it does not.
The standard library does not exclude itself from warnings by default.
So when you turn on WALL, if you include even the simplest header in Visual Studio,
you get a bunch of warnings and you have to selectively disable some of them.
But I think this is actually better because Visual Studio is clean up to W4 and Clang is not.
And GCC is not.
The standard library isn't because they exclude themselves from this.
Anyhow, I like the way the Visual Studio team does it, but I also find it kind of handy
to have these new tools that Rob was pointing out.
Yeah.
Yeah.
Go ahead.
So one thing that I'm noticing is like
one, modules kind of makes this obsolete
and that makes me happy.
What was the other thing?
I was going to say something and I can't remember.
Oh, it was really interesting
like talking about this article on the Slack
because like how different developers have relationships with warnings.
When I'm writing code, I will correct all of the errors and warnings
before doing anything.
But I was talking to this person who, as they're refactoring,
they want to debug without fixing all the warnings.
That was just a really interesting, like difference in,
um,
developer behavior.
Yeah.
Yeah.
Yeah.
Hmm.
Yeah.
I feel like fixing the warnings first is probably going to make my debugging
task easier because there's probably a good reason those warnings were there.
I mean,
on the other hand,
you have like,
uh,
unused variable warnings and stuff like that,
which is what they were referring to.
It's, like, it's an annoying thing.
Yeah, unused variables are significantly less likely to be a warning that's going to cause a bug.
Yeah.
Yeah.
Okay, well, Nicole, at CBBCon this year, you gave a talk on the C++ object model.
Can you tell us a little bit about the talk and how it went?
Yeah, so it was my first talk ever, and it was very nerve-wracking,
and it was a ton of fun.
I feel like I could have prepared better, but otherwise it was a good talk.
And I just kind of...
It was mostly about where in the C++ standard we needed to fix some stuff or work on some wording.
The wording around const and reference member variables inside of classes is a bit weird. It's like if you have a const
reference member, you basically
can never
put a different thing in that space.
Right.
So if you have a vector, for example,
and you have a type
in the vector with a const
reference member, and you push
back, and then you pop back, and then you push back again,
that's like undefined behavior um like like the standard libraries are committing undefined
behavior by doing that because there's no way to actually do this correctly basically uh let's like
dig into that like yeah so what is this push back pop push, pushback, pop, pushback, whatever?
How does that invoke the undefined behavior?
So basically what you're doing is you're constructing an object into storage, right?
Like the storage does not mean anything, but you're putting an object.
It's uninitialized.
It's uninitialized storage.
You're putting an object in there.
Right. uninitialized it's uninitialized storage you're putting an object in there right so the pointer
that the vector uses to like point to the array now points to an object okay you pop back and it
deletes the thing and you push back again and because it had a const or reference member, the new object, the pointer does not point to the new object.
It just points to memory where the new object is located.
Okay.
And this is so that, obviously, implementations can optimize out, like, if you have a const
or reference member, you can check it once and then you never have to check it again,
basically.
Right.
But because of this issue with vector and issues with placement new and stuff,
no implementation actually does this yet.
They do do it for VTables.
Right.
Which is less of a big deal, because if you're changing your VTable,
you deserve to get bitten.
But that's what standard Launder was introduced to do.
Unfortunately, you
basically have to use std launder at
every single access point, and
it's a huge pain, and
it also doesn't work.
For some reason, I can't remember exactly why.
And it also only works for actual
pointer types, as opposed to
custom pointer types as well.
Okay.
So there is an object at a particular memory location.
It has a const value, a const member.
The compiler is allowed to optimize around that.
Yep.
And we've just replaced that object with a new object.
Yep.
And now the next time we go to access that const member we are
potentially invoking undefined behavior because the compiler was allowed to optimize around the
const basically yeah and there's like no way to get around it except for laundering the pointers
except for laundering the pointers but then you have to use the return result of launder
and again it doesn't work with uh custom pointers and stuff right and at that point you have to use the return result of launder. And again, it doesn't work with custom pointers and stuff.
Right.
And at that point, you have significantly crippled the optimizer,
probably if you're laundering every single access
to every single object in a vector, for example.
I mean, I don't think it'd be,
like, except for Vtable optimization,
it shouldn't be a major thing.
Okay.
And for vector, you don't really have issues with Vtables
because you can't really have multiple dynamic type objects.
No, you have Vtable-like things if you have a vector of variance,
but they are not exactly the same thing, yeah.
Yeah.
So it's, like, for that specific use case it's not like a big deal because the compilers don't do the optimization anyways
because it would break code um and it would break standard library code that's supposed to work Um, but like, yeah, so it's kind of a CF.
I'm kind of, um, I'm a little like, since I don't know the details of where exactly the compilers are to optimize, like I've tried to familiarize myself with them, but some of these things are like, you have to know like six different parts of the standard, right?
Yeah. Once you have called the destructor on an object
or reused its memory location,
then the lifetime of the first object has officially ended.
I know that rule.
So at what point, since you've ended the lifetime of the first thing,
and then you've replaced that,
it seems like what is the compiler supposed to do there
exactly
so basically
yeah you end the lifetime of the old object
and even
this is some really
arcane stuff
yeah
our listeners like it when we get more technical
that's good
so let's say you have a pointer that points Our listeners like it when we get more technical. That's good.
So let's say you have a pointer that points to an object.
Yes.
Now, you don't delete it.
You placement destroy.
What is that?
You can just manually call the destructor.
Manually call the destructor.
I don't actually know what that's called, but I'm going to call it manually calling
the destructor.
Manually call the destructor on this
object that's at this certain memory
address.
The pointer now points to nothing,
right?
Well, it points to an invalid
object, I guess, technically at this point.
Yeah, basically.
If you then placement new a new object into that storage,
the pointer points to the new object
if and only if the new object is the same type as the old object
and the type of the objects that are the same because otherwise it wouldn't point to the new object or the type of the objects that are the same,
because otherwise it wouldn't point to the new object.
Um,
because you know,
TBA and stuff.
Um,
and there are no const or reference members.
Oh,
that kind of makes sense.
And there are no const or reference members.
Yeah.
Yeah.
So that's handy or reference member.
Then the old pointer that pointed to the old object does not continue
to point to the new object.
So there is actual specific wording around that.
Yes.
I wish I did not know that now.
If the table changes that it's the same wording, right?
Um, so I don't, I don't believe that it's actually, like, you, I think you can access non-constant non-reference members, but it's accessing the const or reference member.
Like, it, the, the sub-object inside the object that's const or a reference, even though it's not actually an object if it's a reference, not a reference.
Right.
Uh, will, it, like, doesn't point to the new one.
It points to invalid because you
destroyed the... It's
crazy and it's just written
so that your optimizer can trust
that constant reference members
never change, but the issue is
they do.
That's crazy.
I
was not aware of that.
There's a lot of crazy stuff in the c++ standard
tronced pr values they're great just well so i enter go ahead go ahead jason no i was going to
say i interrupted you in the middle of what you were saying to dig into this i was just wondering
where you were going to go next but if rob has a question along these lines first i was just going
to say to to roll back a bit,
I kind of want to know where you got so interested in the C++ object model in the first place.
I mean, we've had listeners who are really interested in compilers,
and they go and build their own compiler.
I just kind of want to know what the history was there.
So the history basically starts with Rust.
I was a Rust programmer for a really long time. I'm not really anymore,
but like I was for a long time. And one of the things that I started kind of getting into like
really unsafe code in Rust. Like that tweet you recently sent out? Yeah. Okay, no one liked the original tweet where I printed my name using the fact that Linux has read-only memory as executable. But everyone liked my tweet that it was like replying to somebody.
Oh, yeah. at you yes it did that yeah okay so everyone liked my tweet about technically everything is
executing memory and i thought that was kind of it made me sad because i'm really proud of that
snippet i guess and unfortunately we've derailed again but for the sake of our listeners you uh
wrote a statement of rust and see if i can get this right and you can correct me if I'm wrong where you put some
effectively hand compiled code in
and then jumped into this code
and executed it
which is the kind of thing that you would say Rust shouldn't be
allowed to do because Rust is
very safety conscious
but there's an unsafe keyword
so you can do whatever the heck you want
including execute
undefined behavior okay that's that's kind of like so the thing about rust is you the idea is that
you can't have undefined behavior if you don't have the unsafe keyword and the unsafe keyword
allows you to do undefined behavior that's not true because lovm is bad but no lvm is awesome but it does do some stuff that like you cannot
work around like for example a into float cast and float to in cast uh are undefined behavior
if they're outside the bounds um and you cannot do anything about it. In Rust. In Rust. But in LLVM semantics.
So there's no like,
just do whatever the hardware does.
Right.
Like the optimizer will always assume
that an into float or float to int cast
is undefined behavior
if it goes out of bounds.
Which means that you can like
do whatever the heck you want in Rust
if you have an out of bounds float to int
or into float cast.
Okay.
And then also, like, infinite loops,
they're
optimizable in C++. They're not optimizable
in C and Rust.
So, or, like,
infinite loops without side effects.
Right. But
LLVM just assumes they're optimizable,
which is bad because it breaks
C and Rust.
Interesting. I think they're fixingizable, which is bad because it breaks C and Rust. Oh, interesting.
I think they're fixing that with an intrinsic...
But anyways, I got into unsafe code and Rust.
And one of the things that's a big part of unsafe code is this function in the standard library called transmute,
which is basically C++.
You'd call it bit cast.
Like it's take the bits of one object,
take the bits of one object,
mem copy them into another,
an object of a different type,
basically.
And,
and Rust like checks that they're the same size and it,
it's incredibly unsafe and people use it for pointer casts and it's really, really, really not good.
Um, this, it's, it's a big thing, anyways.
Um, but, like, as part of the Transmute, you have to be interested in, like, object models and how all that works together.
So, I got interested in the rest of object model and then as i kind of fell into c++
i got really interested in references because references are really cool like i feel like
references are probably c++ like one of c++'s top features interesting unfortunately not
super ergonomic and there are some mistakes that were made in the design of references um in my opinion um like for example uh forwarding references i believe are i would i would argue
they're a design mistake um but basically it's like a really it's um they're a really cool feature
because they're c++ is the only language that I know of that allows you to have a value which is an object.
That kind of makes sense.
The reference itself, you're saying.
The reference itself is a value which is an object.
You are able to pass objects around as if they were just normal values.
And you can pass values around as well.
As opposed to something like OCaml,
where everything is a reference.
In C++, you have both reference and value semantics,
which is really, really cool.
And I'm not being super awesome,
like talking about, well,
not talking about this super well,
but it's really cool cool is the point.
And it fascinated me.
And then I got into the object model of C++ through that, kind of.
And, like, reading the standard a lot,
because the standard's really fun to read.
So I believe you are officially the only guest we've ever had
who would actually say the standard is really fun to read.
And we've had people on who work on the standard yes it's like it's it's legal language it's really it's really enjoyable to like
suss out the actual intended meaning and like i don't i don't know it's fun it's fun in my classes
i try to do a little bit of like uh learning how to read the standard for when you need it.
Not like reading the standard for fun and pleasure or something.
I don't think of it as bedtime reading.
I mean, clearly you've never read the...
Michael Case did the Beat.
Oh.
That is actually in the C++ standard and I love it
so much
that was the secret
lightning talk from meeting
C++ 2016
I think so yeah
I've like literally shown that to
people who are not programmers and been like
look C++ programmers are awesome.
And you have fun
stuff like the.zombie
namespace in the standard,
which is for
things that are deprecated, I think.
The standard is a barrel of
laughs. Let's just say that.
Alright, everyone, you've heard it from Nicole.
You should have fun reading the standard
after this episode.
Yeah. And also reading old standards
is really fun because you're like,
what the heck were they thinking?
Like, there is a
clause in the C++03
standard that basically says
if you bind a reference
to a temporary, temporary or an object of the same type, the compiler is allowed to emit infinite copies.
Allowed to emit infinite copies.
Yeah.
There's an implementer's note that says, note, you may want to stop because otherwise you're, it would be useless or it was like,
or no,
no,
no.
You might want to stop at some point because otherwise you'll have infinite
recursion.
This seems like,
um,
it must've been around the wording that I think most people aren't maybe
necessarily familiar with.
And I honestly need to spend a little bit more time with,
but how you can extend the lifetime of a,
of an object returned from a function by assigning it to a const reference.
It's not actually related to that.
It's not related to that. Okay.
You know, it's like there's... So basically, there's a thing which says there's two things
you can do with a temporary to bind it to a const reference. You can copy it into a new temporary of the the reference type or you can
bind the temporary object to the reference okay but the issue is it doesn't say like you only have
to you can only copy once it just has those two things next to each other okay so it says like you
put the object into or you put you put the temporary object
into a new object and
bind the const reference to it.
And in order to bind a const reference,
you do that, or
you just bind
the reference to the temporary.
And it doesn't say you can only do this
copy once. It has
an implementer's note. You might want to stop
at some point because it will infinite recursion otherwise all right there's a lot of really silly wording
i wanted to interrupt this discussion for just a moment to bring you a word from our sponsors
you have an extensive test suite right you're using tdd continuous integration and other best
practices but do all of your tests pass all the time getting to the bottom of intermittent and obscure test failures is crucial if you want to get the
full value from these practices and undo's live recorder technology allows you to easily fix the
bugs that don't otherwise get fixed capture recordings of failing tests in your test suites
and debug them offline so that you can collaborate with your development team and customers
get your software out of development and into production much more quickly,
and be confident that it is of higher quality.
Visit undo.io to see how they can help you find out exactly what your software really did
as opposed to what you expected it to do, and fix your bugs in minutes, not weeks.
So as someone who studies the object model and reads the standard, what do you think is something the average C++ developer should know about the C++ object model that they probably don't already?
Honestly, there's not too much that you need to worry about.
It mostly just does the right thing like like except for some major like some issues with constant
reference members um and this isn't really related to the object model but constant pr values as well
like those three things are really the only major things that you kind of need to worry about
um so constant reference members basically the lesson to take home is don't ever use them. Just use pointer
and mutable or not.
Non-const members.
Or like std reference member or something.
Well, const members are very difficult to
work with effectively.
Right. So just don't
worry about that part of the standard.
Just don't use const or reference members
is basically the idea.
And then on const br values basically just
never return a const object from a function because the c++ standard does some weird stuff with it
yeah it's generally considered best practice that that never does what you
want it to actually accomplish so stop doing it right. Right. Oh, and always put ampersand on your operator equals.
Ref qualify your operator equals, so you can do as the ints do
and not take L values.
Operator ref.
You say always ref qualify your operator equals.
Operator equals.
Specifically the copy operator or the move assignment? Anything that is an operator equals. Specifically the copy operator or the move operator or move assignment?
Anything that is an operator equals.
Just because then you can't say
if your class is foo,
foo open print close print equals other foo.
Right.
So you can't assign to a temporary effectively.
Yeah, basically.
Okay, so if I were to say I want the default implementation that the compiler is going to provide for me, for my assignment operator, would you recommend that you do the ref qualified equals default?
Yeah.
Does that prevent the compiler from creating the rvalue ref qualified one, or do I need to explicitly delete that one?
You know, I haven't actually checked.
That's an interesting question.
I'm going to check on the compiler explorer,
because that is curious to me.
I'm guessing it would prevent it from being created, or it will...
I do, too?
Because it can't create the non-R-value reference-qualified one
because you can't have both reference-qualified
and non-reference-qualified versions that overload each other.
And by default, it's not going to make the R-value-qualified one.
Yeah.
So we did some investigation that Rob has edited out,
and it's not entirely clear what the compiler is doing at this point,
and it's going to take some more investigation,
and hopefully Nicole will write up an article on this or something
that we can link to later.
Sure, definitely do that.
I just volunteered you for that.
Okay, good.
But yeah, basically, as long as you avoid
returning const
objects from functions like
const foo bar open print
close print
as long as you avoid const and reference
members and as long as you
no those are the two big things
that like
the C++ standard will do what you expect it to
there are
some like C rules that you cannot
follow like the whole union thing like you can bitcast it will do what you expect it to. There are some C rules that you cannot follow,
like the whole union thing.
You can bitcast it from unions
in C, but you can't in C++.
But other than some stuff like that,
it's mostly just, it does what you
expect it to.
Honestly, Ximity has
done a really great job at
C++ 11 and up
models.
They are absolutely fantastic
as far as object
models and all that goes,
in my humble opinion.
Yeah, we've had other guests say that the C++11
object model literally changed their
business because it made more
things possible. Memory model
and object model, yeah.
The memory model's great. yeah yeah the uh the memory model is great
the reference model is great the object like c++ 11 turned like a pretty crappy language in c++
03 into like a freaking fantastic language it's it's like the standards committee does not get
enough uh recognition for how much work they've done.
So as someone who used to be more involved with the Rust community,
what would you say that C++ could maybe learn from Rust?
More static analysis is, I think, always a good thing.
I feel like something like Sal,
Microsoft Sal,
which are those really weird C things that you write in, like out param and stuff in the Microsoft.
I don't think either one of us is talking.
Yeah, we're not sure. So in Windows code, basically, there's a lot of like attributes.
Okay.
That you like write around stuff like for example this size t parameter is the
length of this other pointer parameter okay so you can do like good um annotation or not
annotation static analysis around that right um and you're losing a lot less information as you
do function calls and you can specify in parameter, out parameter, in out parameter, or whatever.
Exactly.
And I think that it would be good to, like, it would be interesting to add, like, lifetime
annotations in that kind of way.
Because I think lifetimes are a really big deal, and they're really cool.
The other things that I think C++ could learn from REST is more safety by default.
Like, one of the things that C++ does really well is fast by default,
but for most things,
you don't actually need it to be that fast.
Like, I think that ftrapv,
like, if you overflow an integer, you trap,
as opposed to undefined behavior,
would be, like, a really good default
to have for compilers.
Interesting.
Um,
and in general stuff like,
like,
uh,
like operator,
open bracket,
close bracket for vector.
It should trap.
If you go,
if you like do a buffer,
buffer overflow,
because that's like a safety issue at that point.
And it's like,
it will screw up stuff um and i
think that c++ people are a little bit too obsessed with speed over safety um and specifically
making the easiest path the unsafe speedy one right like it would be totally fine to have like operator open bracket close bracket on vector
check for overflow and trap if it overflowed and then just have like an unsafe get or unchecked
get or something as opposed to the opposite of what we have right now where the index operator
is unsafe but then we have dot hat if you want it to do a check. Yeah, and also there's a lot of exception throwing in the C++ set.
.hat will throw an exception if you do it.
You'd prefer just a crash.
I would prefer just a crash because you're saying this is a bug,
but it's not going to fuck up the rest of your code.
Or it's not going to screw up your, sorry for saying, it's not going to screw up your,
uh,
uh,
your,
uh,
your security or whatever.
It's just going to crash.
Right.
You have gotten to a point where you are,
your,
your business logic is incorrect and we are going to crash instead of letting
you continue with that.
Interesting.
So how do you feel about the,
uh, or if you spend any time at all looking at like the checked integer, uh, library kinds of things that do some of the,
what you're talking about, but you have to, well, I guess you already said that you would prefer
that the easy path was the safer path as opposed to the way around. But I like unsigned overflow
is like, why is that? Why can't I have trapping unsigned overflow? And like undefined behavior unsigned overflow that I really dislike that about, like the fact that unsigned is overflowable is weird to me.
That is an old history where that was actually the desired behavior and some 16 bit things and eight bit things back in the day.
Yeah,
I know.
And it also frustrates me as like a modern developer.
Right.
Cause like,
I can't say,
you know,
unsigned is trapping on overflow because some other library might depend on
it overflowing.
And it's just a big crock of annoyance.
Right.
But yeah, I feel like more checks are a big deal.
Also, Rust allows you to do really, really unsafe things
behind the unsafe keyword.
Like, you could just get the pointer and the size out of a vector,
or pointer size capacity out of a vector,
and then recreate them.
Okay.
And I've wanted that a lot in C++,
where I'm, like, say, writing a span type
that's owning,
and I want to take the memory from a vector,
or, like, put the memory back into a vector.
Right.
It would be useful to have these unsafe
utility methods.
Okay.
That's interesting to hear that you want
some of the unsafe features of Rust
brought into C++, but you want the safe features
of... you also want the safe features
of Rust, I guess, brought into C++.
Yeah. C++
is kind of in the middle in
between rust so you have like safe rust and unsafe rust c++ is like safer than unsafe rust
but more unsafe than safe rust and i want it to kind of spread out okay like as safe as safe
rust and as unsafe as unsafe rust interesting because rust lets you do some insane insane things so you're a barista
you read the C++ standard
for fun
and you've started with rust
you said you're working on OCaml largely now
yeah I'm building a compiler
for a language that I'm designing and i got fed up with rust
so i'm now writing it in this recent taxing of a camel called reason ml done by facebook which i
really like um i didn't know that facebook had been involved in the okamal world at all
yeah actually like 50% of Facebook Messenger
is written in this re-syntaxing of OCaml
called ReasonML.
And ReasonML is just basically OCaml,
but with kind of more JavaScript-y syntax.
Okay.
Which is much nicer to my eyes,
because I really dislike...
There are a lot of issues with OCaml syntax
that I'm not going to go into,
but ReasonML kind of fixes most of them, if not all of them.
And JavaScript syntax is actually kind of pretty.
Kind of.
I like braces and semicolons.
What can I say?
So what's next, though?
I mean, pursuing a language, writing your own language is a hard thing.
And I'm just trying to remember, I think it was when we had Strewstrip on,
that he has said something along the lines of,
don't ever create your own language because either it'll be successful
and you'll be stuck doing it for the rest of your life or it'll fail.
Something along those lines.
Something along those lines.
I mean, so if it fails, I got a lot of knowledge.
Right.
And I can yell at the C++ community to add stuff.
And if it doesn't fail,
then yay, I can write stuff in a language
that I like, that has
linear types,
and is similar to ML,
or is like ML,
but with C++ level
performance. That's great to me.
And has destructors and all that, because
every language should have destructors.
Destructors are amazing.
Yeah, I thought it was very interesting
when you said that references are the main feature of C++
when, generally speaking,
the answer everyone gives is destructors.
So the main features of C++, in my opinion,
are destructors, references,
from a programming language design perspective not from like a
using c++ design right um references are really cool and i don't know any other language that
really does them like c++ does i think that's sad um it has really cool the destructors obviously and the idea of
value semantics is really cool
if not executed super
well
copy by default is a really bad default
and
it's unfortunate that
that's the way that C++ went
it makes sense that that's the way that C++ went
because of the early days
but in my opinion it would have been better
to do kind of like an affine type system
similar to Rust where like
it's moved by default and you just like
yeah go ahead
and then like you don't call the destructor on a move from object
okay right
like the compiler does that as opposed to the program
right so i'm just curious what's next though i mean you're working on this programming language
do you have any plans to go into programming full-time or yeah well so uh i'm i finished
my associate's degree and i'm gonna go do a master's at not about masters a bachelor's at uh
western washington university that's great in the north of washington computer science Master's at, not a master's, a bachelor's at Western Washington University.
That's great.
In the north of Washington.
Computer science?
Math.
Math, okay.
Yeah, because math is, computer science, if you're not going to, like, a very few specific schools,
is not, in my experience, a very well-taught field.
It's like, it's very it's very, um, inconsistent.
Okay. Right. Uh, I mean, it's been a while since I've been in university,
17 years since I graduated. My computer science program was highly theoretical with enough math
that if I had taken one extra math class, I would have gotten a minor in math.
But due to other reasons,
I didn't actually end up,
I started down that road,
didn't manage to complete it.
So I did not get a minor in math,
but yeah.
And I,
I know that as some,
like,
I'm super interested in like the theoretical stuff and I don't want to do a
lot of the programming stuff.
Cause like I've done a lot of that.
I've programmed for like 10 years. I've programmed for 10 years.
It's fine.
I need the practice
of object-oriented programming.
Right.
Okay.
Was there anything else you wanted to share?
Where can people find you online?
Do you have a blog, Twitter?
I have a Twitter.
I do have a blog, but i haven't updated it in like
two years or something uh the last the last update that i have on it is like my my so there
there's a style guide in rust that was terrible and like had a lot of issues. And the default formatting tool
did that style that was really not very good.
And so I wrote a competing style guide
and got myself on the style team
and now, in my opinion,
the Rust style is fairly good.
It's better than it was.
Match statements,
the variant switching statement,
they still double indent, which annoys me.
But other than that, it's really good.
Okay.
I kind of wanted to talk about Mason a little bit, actually.
Sure.
Because one of the things is, like, the thing, the issue that I have with Mason is, like, this is the best that the C++ community can come up with.
It's kind of depressing.
I was trying to run Nissan the other day and try it out, and it's incredibly unintuitive.
And I feel like C++ needs to get something like Cargo or OCaml's JBuilder that just makes it easy
and you don't have to worry about it too much.
And it just does the defaults well.
The problem is C++ has so many more compilers and toolchains and everything to try to work
with, right?
I mean, it does, but like as long...
So one of the things that I have an issue with
with like modern C++ build systems,
which are not all that modern really,
is they don't enforce a directory layout.
Right.
Which means that you have to put
all the directory layout information into the build file. So like, for example, you have to put all the directory layout information into the build file.
So, like, for example, you have to, apparently in Mison,
you have to say that your include directories are in include.
Like, that doesn't seem like a, like, you should just have a single build layout,
and, like, that's fine.
And, like, you can do, like, a toml file.
And I feel like C++ needs to make that shift at some point soon.
Because it's putting off new programmers to C++.
If somebody wants to pick up Rust, they install a compiler with RustUp.
Oh, and the compiler installation is also really bad.
But they install a compiler with Rust up,
and it installs Cargo and everything as well.
And then you do Cargo new project name,
or Cargo new minus minus bin project name,
and you're done.
You have a project.
All you have to do is start editing Rust code.
Whereas with C++, you have to do all of this setup.
And to build Mison,
and Mison looks like one of the better options out there, if not, like one of the best,
you still have to use like Ninja and like all this confusing stuff that is like incredibly
weird to like a new programmer. Yeah. You know, so in your hypothetical build system that you've thought about but haven't
implemented yet would you enforce
a specific like file
layout for the project
yes okay like hands down
like you'd have
a source directory and include directory
and in your source directory you'd have like
the module files and also the C++ files
like that
just definitely needs to happen, in my opinion,
is an actually enforced directory layout.
And old projects won't be able to go over to it,
unfortunately, easily.
But it's not a big deal
as long as you can interface with old build systems.
The thing about ocaml
um the new user experience isn't great either especially on windows but the
build system is pretty simple like jbuild is really simple um uh it's not great but it's
it's pretty simple but the thing is like this new build system can also interface with all of the old build systems.
Okay.
And so you don't have to worry about having an old build system with a new build system.
You just have a package, and then you can interface with that package.
Interesting.
Yeah.
And I think that C++ could do something similar.
Right.
It's definitely something we definitely need improvement in the C++ community.
Yeah.
The big issue is new users.
People are getting turned off C++, and it really sucks,
because C++ is a really good language.
And it just has a terrible build story,
and people don't use C++ because of it.
Okay, well it's been great having you on the show today, Nicole.
Yeah. It's been fun. Yeah. 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 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.