CppCast - Freestanding Proposal
Episode Date: May 17, 2018Rob and Jason are joined by Ben Craig to discuss his proposal for a freestanding C++ Library. Ben is a Principal Software Engineer at National Instruments, primarily developing device drivers ...for various operating systems (Windows, Linux, Mac, OpenRTOS, vxWorks, ETS Pharlap), and occasionally tinkering with the firmware side of things. Ben is an occasional contributor to libc++ and Apache Thrift. News Convert Macro to Constexpr in VS 2017 CppCon 2018 Registration is Open How to Adopt Modern C++17 into your C++ Code 7++ Reasons to Move Your C++ Code into Visual Studio 2017 Effective C++/WinRT for UWP and Win32 C++ Insights P0709 Zero overhead deterministic exceptions Ben Craig Ben Craig's GitHub Links Freestanding Proposal Freestanding Trip Report: emBO++ and Jacksonville wg21 2018 experience Sponsors PVS-Studio The Evil within the Comparison Functions Patreon CppCast Patreon Hosts @robwirving @lefticus
Transcript
Discussion (0)
Episode 150 of CppCast with guest Ben Craig recorded May 16th, 2018.
This episode of CppCast is sponsored by PVS Studio.
One of the most powerful static analyzers for your C, C++, and C-sharp source code,
PVS Studio will let you detect errors and potential vulnerabilities at the earliest stage.
Try the demo version today at viva64.com.
In this episode, we talk about MSVC announcements and new exception proposal.
And we talk to Ben Craig from national instruments.
Ben talks to us about his proposal for a freestanding C plus plus standard
library. Welcome to episode 150 of CppCast, the only 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? How's C++ Now?
C++ Now is great as always small
conference easy to get to meet everyone i think it was in matt's uh trip report he said with 150
people there you get to know pretty much everyone by name my memory for names is not quite that good
but it is true that there's an awful lot of people there that you recognize get to know quickly see the
same people in each session and whatever it's it's a good conference i didn't even think to look for
trip reports for the uh show notes this week for the for the links we'll have to look for some for
next week yeah there's um i think five or six out now okay well at the top of our sort of like treated piece of feedback, this week we got an email from Chris Klein, and he wrote that he just noticed that Visual Studio 2017ion lupru who we've had on the show before
uh posted a little gif showing this feature in action and it's pretty cool this new option to
convert macros to constexpr wow i had this one yeah yeah that's uh that's pretty fancy. Very fancy.
We will have to have someone from Microsoft on soon to talk about the latest announcements
that we'll touch on a little bit in the news.
But I don't think we've had anyone from Microsoft in a while,
so there's probably a lot to discuss.
Yeah, it's definitely been a while.
This is pretty darn cool.
I'm sorry, I have this GIF playing, and it's just like, it's a little bit, well, it's interesting.
It converts it to a constexpr variable template by default, and it looks pretty darn cool.
Yeah.
Okay, 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 Ben Craig.
Ben is a principal software engineer
at National Instruments,
primarily developing device drivers
for various operating systems,
including Windows, Linux, Mac,
OpenRTOS, VXWorks, ETS, FarLab,
and occasionally tinkering
with the firmware side of things.
Ben is an occasional contributor to LibC++ and Apache Thrift.
Ben, welcome to the show.
Hey, good to be here.
What is the Apache Thrift project? I don't think I've ever heard of that.
So that is an RPC framework originated in Facebook, and then they donated it to Apache. And so I haven't done a whole lot with that recently,
but technically I'm on the project management committee,
even though I've been a really bad maintainer as of late.
Okay, so is it an RPC intended for C++, or is it like a cross-language kind of thing?
It's a cross-language.
It has bindings for 20-something different languages, including C++.
And C++ is one of the more active languages in there,
largely because of Facebook and people like me poking at it.
So, yeah.
That's cool.
Okay, well, Ben, we we got a couple news articles to discuss
feel free to comment on any of these and then we'll start talking to you more about your
proposal okay thanks i'll do that okay so first one is just a announcement i think we may have
touched on this before but cpp con 2018 registration is now officially open. Yes, it is. Let's see. That was April 26th that was posted.
I don't recall if we actually mentioned that the registration is open, but yes.
Yeah, I think we mentioned the call for submissions, but now registration for general attendees
is open as well. Just an FYI
for listeners, if they go and click on it, the lodging info still
has not been updated for 2018.
So don't be confused by the fact that the lodging says that everything is booked and closed.
That's just because that's still 2017's lodging stuff.
Yeah, I think you have some time before you worry about lodging anyway.
Yeah, 129 days remaining.
Yeah.
Okay, next one.
I mentioned that there's a lot of Microsoft announcements this past week.
They had their annual build conference,
and although it's not really a big C++ event,
they did announce some C++ new features with Visual C++.
And the big one that we've kind of been leading up to for a while
is that they are now announcing that MSVC conforms to the C++. And the big one that we've kind of been leading up to for a while is that they are now
announcing that MSVC
conforms to the C++ standard.
They made it. Mostly.
Mostly?
I mean, yeah.
Yes. A couple little things.
And you do need to use
certain compiler switches, I believe.
But
they're calling it conformance,
and they're including C++17 in that.
Yeah, like...
Go ahead.
Well, like Ben said,
modulo some bugs, right, basically.
Right.
Yeah, the two big libraries
that a lot of people are chomping at the bit to use
are going to be rangesv3 and boosthana,
and those two still don't work because of some of
the bugs but in their favor in visual studios favor they are the first uh of the big three
implementations to actually have a parallel stl algorithm parallel stl stl implementation
yeah yeah that's a good point yeah that's just's just, uh, I, I, I try to not get
too cynical about this one on, on CBP cast, but when I see that, you know, C plus plus 17
conformance has been met. Oh, except we don't have parallel STL yet. Oh, except we don't have file
system yet. Right. Like, I feel like those are kind of big deals. And like you just pointed out,
visual studio has both of those.
Right.
A lot of those announcements seem like they will come from the compiler people
and not necessarily the standard library people.
And sometimes it seems like they don't necessarily advertise the tool chain as a whole.
But at least as far as features are concerned,
Visual Studio 2017 seems to have everything
except for the things that no one can figure out
how to implement, like floating point
charcon.
Wait a minute.
Floating point character constants?
No, no. The charcon
header
lets you turn strings to
ints and back and forth,
and that part's there, but floating point, the standards have very tight restrictions that may just be unimplementable.
I love that when you're following some of the standard library implementers on Twitter,
and you'll occasionally see some tweet from one of them that's like,
oh, and we just realized that it's actually impossible
to implement this thing that was approved.
So now we have a bug report to the standard.
Yep.
Yeah, that's fun.
The other thing I wanted to mention is, like I said,
Build was last week for Microsoft,
and there were a couple C++ talks that I wanted to highlight
and let listeners know about.
There was one talk from Herb, and that was how to adopt modern C++17 to your C++ code.
There was one from Marion Lupreux, who we just mentioned, doing the constexpr macro conversions.
And his talk is 7++ reasons to move your C++ code into Visual Studio 2017.
That can't compile.
Sorry. reasons to move your C++ code into Visual Studio 2017. That can't compile! And the only thing I want to mention is that that was the same title of a talk he did last year.
So I'm not sure if he updated it or if it's almost the same talk.
I need to watch that one to see what he did with that.
I don't know.
And the other one was Effective C++ WinRT for UWP and Win32.
And that was a Kenny Kerr talk about C++ and WinRT.
I do love that Herb skirted around the question of
what is the definition of modern C++ by making the title of his talk
Modern C++17.
Yeah, that was a good one.
I don't know if that was 100% intentional,
like if that was the reason he named it that, but it works.
Yeah, it works.
I started watching the beginning of Herbstalk, and it seemed to be a pretty good one.
It was more kind of aimed at that audience who maybe haven't been following C++ standard updates as well,
and kind of giving them an overview of what's changed in the language.
I'm curious, Ben, since you say that you do some drivers for Windows, Linux, Mac, does
that imply you do use Visual Studio, I would believe?
For Windows drivers.
The Visual Studio compiler for Windows drivers, they have some support to use the Visual Studio IDE in the kernel,
but for the most part, we're just using the compiler and not the IDE for the main stuff.
Now, you can still pull it all up in a project and use a lot of the features there,
but yes, it is mainly Visual Studio.
Some people have suggested we use Clang in the kernel,
targeting the kernel,
but that's a little bit more risk than we're willing to bite off.
It sounds unwise for a shipping product
until someone else has proven that this is a safe, stable way to do things,
or until Microsoft gives their stamp of approval on it or something, personally.
I'd be willing to do it if we were an organization large enough to have a team contributing patches
to clang so like uh google is shipping chrome with uh on windows built with clang and they
have a team large enough to to fix Clang when there's a problem.
National Instruments does not have that big of a team for that kind of thing.
Right. So do these releases for Visual Studio, the new compilers coming out that is from Microsoft, do they directly affect you?
Can you start rolling C++17 features into your drivers now and that would be okay?
Depending upon which features, yes. So the language
features we normally were able to adopt, most of them
as we upgrade compilers, we're mostly
on Visual Studio 2015 now.
So, well, you still have to be careful with certain features,
like magic statics, thread-safe statics.
We can't use that feature.
We have to turn it off in kernel mode.
So we can talk about that a little bit more
once we get to the interview part, I guess.
Sure.
Sure, okay, yeah.
That ties it very well into the kind
of things that i'm i'm looking at well i'll be sure to bring it back up once we get there yeah
okay uh another thing i wanted to highlight is this uh new online compiler tool this one is
called c++ insights and uh this one basically is is showing you kind of the extra
generated code that the compiler puts in in addition to what you write out so it's not showing
assembly the way compiler explorer does it's instead just showing you all the extra code
uh that the compiler generates for you yeah Yeah, this is like the middle land
that most people don't think about.
This isn't what the preprocessor did.
This isn't what the actual assembly output looks like.
This is what transformations to your code
did the compiler do based on what the standard says
that it needs to do for various things.
And I like the example,
if you just go to cppinsights.io, they show you using
the new like for each loop, how it generates a standard for loop for you in order to do that.
I thought that was interesting. Yeah. And understanding what it does,
there has some real implications and understanding what your code is doing.
Like if you play around with that, you'll understand why ranged
for loop
init is being added
in C++ 20
specifically.
So I played around with it
a little bit, and there were
good parts that
I liked. I made a function off to the
side that returned a stood vector
by value, and it made a little comment in there saying
oh, this is NRVOD, so name return
value optimization. I thought that was neat.
I was kind of expecting it to put some comments
or change up my code some to, well, one, mention where destructors
are automatically generated,
possibly mention a little bit more about how exceptions are dealt with,
or if I have a concrete function that's calling a template function,
maybe tell me which template specialization I got.
And those things weren't there, but this seems like a good starting point.
Yeah, likewise, I played with the Lambda example,
and it's interesting to see it show effectively
what code was generated for the Lambda for you.
But then I made it into a generic Lambda
that I coerced into two different types of function pointers,
which is totally allowed,
and the resulting code that it generated,
I'm almost positive could not actually compile.
But it still gives you pretty good insight as to what the compiler needed to do to make these things happen
okay and then this last one uh we mentioned uh herb's talk at build he also just came out with
this new paper uh zero overhead deterministic exceptions. And, uh, actually I might let the two of you
talk more about this. Cause I think Ben, you, you suggested that, uh, we, we talk about this one,
but it's a really interesting paper, basically changing the way exceptions or introducing a new
way of, of doing exceptions and C plus plus that I think the goal is to make it more palatable to
game developers and embedded developers. Is that right?
That is my take on it.
I'm very excited about this paper.
I've got to provide draft feedback for it, along with about 20 other people, including like Phil Nash from last week.
This was the paper that he was alluding to.
And if this paper or something similar goes into it,
then I'll be able to start using the exception programming model in lots of places where I just couldn't before,
including kernel embedded spaces.
And then I get the performance characteristics of return codes, both the good parts and the bad parts.
But I'm using return codes everywhere right now, so I'm comfortable with those tradeoffs.
So I guess, well, I mean, since we're to this point in the conversation now, what are the, if you don't mind, what are the problems with exceptions as they are today that would prevent you from using them in the kernel and in the embedded space?
So in some cases, there is a very direct technical problem. So if you build a Windows kernel driver
and you pass the slash kernel flag like you're supposed to then anytime you utter the
words try catch throw uh you get a compiler error uh so there's that in the way but there's flat
out forbidden yes uh there are technical issues as well in that uh there's a lot that the loader has to do to stitch together exception handling tables, and a lot of kernel mode stuff just doesn't want to do that.
On embedded systems, technically you can do just about anything you want.
You control the entire system, but there's a whole lot of space overhead. Even if you never
do a throw
or try or catch,
if the compiler can't
prove that
nothing ever throws
through link time
optimizations or something like that,
then a lot of that code still has to be
omitted. And since it's so
hard, a lot of compilers don't even try to remove all of that code.
They just assume that if you're not going to throw or catch or anything like that,
you probably just pass the flag, dash F, no exceptions.
So yeah, there's a huge space penalty.
But then there's some stuff kind of behind the scenes that you may not think about.
So if you're familiar with the uncaught exceptions function,
the information from the runtime for when you throw an exception to increment that number,
well, that's communicated through thread local storage.
None of the kernel operating systems
in the kernel,
none of those Windows, Linux, Mac,
OpenRTOS,
none of those support thread local storage
in the kernel for arbitrary data.
So uncaught exceptions just flat out won't work there.
And then you've got on embedded systems,
you'd have to implement thread local storage.
And there's a whole lot of handshaking
that has to happen between the compiler,
the runtime library, the OS.
All of those things have to be in agreement
on the ABI of thread local storage.
And that's a lot of work for an embedded developer
to do. They could do it,
but in
the driver space, well, I
don't have access to the Windows kernel
source code, so I can't do it there.
Those are a lot of
the reasons of why I cannot.
I would love to. I like
the exception programming model.
It is unfortunate that I can't use them right now, but I am hopeful.
I don't think you mentioned this, but I believe exceptions also, generally speaking, require dynamic allocation, right?
It depends upon which exceptions you are talking about. So the Itanium ABI, so the ABI that pretty much everyone but Microsoft uses, those allocate the exception object on the heap, and embedded systems frequently don't have a heap.
With the Microsoft ABI, they create a big chunk – they make a big stack allocation and put the exception object there.
And that also causes a technical problem in that in kernel mode and on embedded systems, the size of your stack is typically pretty small.
I've dealt with embedded systems where the size of the stack was 512 bytes. On, I want to say Windows 64-bit
by default has a 16k
kernel stack.
Some older versions of Linux
had a 4k kernel stack.
Well, the stack
allocations that the Microsoft
ABI makes
are like, on 32-bit
it's like a 4K
allocation, and
on 64-bit, it's an 8K
allocation, and those
don't compare favorably to
the total stack size you have available.
And I'm guessing that a stack overflow
in kernel mode would be not good.
Very unpleasant.
Screens turning blue are a very common thing that happens there.
Yes.
If you're lucky.
If you're unlucky, then it'll corrupt your hard drive file system or something like that.
How does this compare to the proposal that Herb is doing then?
It compares very well.
So if you've seen things like stood expected,
then this is doing slightly better
from the code generation standpoint
because it's in the language
so you can make a little bit better assumptions.
But it's basically using the return channel.
Yes, so wherever you would put the return value beforehand on the stacker and registers,
well, that's also where the error code information is coming out.
And then depending upon which system you're on, the hope is that there's an extra flag bit somewhere that can be used by the ABI.
So the generated code will check that flag bit and based off of that know whether it's a normal return or an error return and make decisions based off of that. So the stack usage is going to be basically the same as the existing return code is,
and the performance is going to be about the same, and the space usage will be roughly linear with how much you use it, whereas with current dynamic exceptions,
the space overhead is roughly linear
with the size of your entire program.
Okay.
So, yes, the size overhead,
the lowered system requirements,
you don't have to heap allocate anything,
you don't need a giant stack allocation,
you just need enough...
You're using stack that you already needed for the most
part. All of those things compare better. There's still
the question of the thread local storage thing because
in user mode and other hosted environments, you still
want to be able to have things like uncaught exceptions work.
That's something that I'll have to be able to have things like uncaught exceptions work so that's something that i'll
have to be working on to make sure that uh the the that thread local storage isn't used just in the
uh in in freestanding environment uh where you're fine not calling uncaught exceptions
so since you just said the word freestanding maybe it's a good time to transition into that. So we talked about your trip report from Embo++ and the Jacksonville
ISO meeting a couple weeks back. Can you remind our listeners a little bit about what the
freestanding proposal is that you discussed there? Yes. So in C++, there's two classes of conforming implementations.
There's a hosted implementation, which is what pretty much everyone uses, and there's this thing called a freestanding implementation.
And the freestanding implementation, what the standard says is that it's there to provide C++
for a system without any operating system.
Right now, I mean, that's what it says,
but it doesn't actually do that right now.
It requires a lot of things to be present
that just aren't going to work.
Things like uncaught exceptions.
It requires operator new and delete to be present aren't going to work. Things like uncaught exceptions, it requires
operator new and delete to be present, and all sorts of other things.
So,
but that's
on the things that won't work.
There's tons of things,
well, from my perspective, tons of
things that will work just fine
that aren't there.
A freestanding implementation doesn't have
memcopy right now. It isn't required
to have memcopy. It's allowed to when pretty much
all the systems do.
There's not a whole lot of
A2I.
Sorry, not A2I.
ABS, absolute value of an
integer. I'd be hard-pressed to find
a system, no matter how
small, to where the absolute value
of an integer wouldn't work.
But it's
not currently in the freestanding.
But it's not currently there. It's not required
to be there.
So the proposal that
I made in Albuquerque,
and I'm up now to revision 2
that will be presented in Rappersville by
Odin Holmes,
I add lots of things to freestanding that should work pretty much anywhere.
Modulo size restrictions.
I say that because, okay, if you've got a system with one kilobyte of storage space, you may not be able to use std sort, for example, because there's a lot of optimizations in std sort and it's a recursive function and things like that.
But it's still just doing things that are just touching memory and doing math and no operating system requirements, no requirements on huge global data structures.
So adding things like the algorithms,
adding lots of things that happen at compile time,
like a lot of the duration stuff from the chrono headers.
Not the clock interaction, but the duration math.
All of that should be fine.
I've got a whole bunch of other things that I'm adding as well
that probably should have been in there in the first place.
I don't like set jump and long jump,
but there's no reason that it shouldn't work in a freestanding environment.
There's a lot of
wide character stuff,
like WCSLin, the
Sterlin version, the Sterlin
for wide characters.
There's not a whole lot of use cases
for it, but there's no reason it shouldn't work.
Even after I put that in my paper,
I found out from someone that
EFI, so the thing between, so there's BIOS, there's UEFI, and in between those time periods there was EFI.
EFI, the code that runs on there, uses 16-bit wide characters.
Why not support them as well if it doesn't cost anything for people that aren't using it?
So I add a lot of things like that.
And, yeah, I got pretty good reception for that in Albuquerque.
A lot of that was kind of just saying, okay, this is the general idea.
We didn't get the specifics of what was there and wasn't there.
In Albuquerque, I was still removing things.
So I pitched to – I suggested removing the type info header and the exception header.
And I actually got a good – people said, okay, yeah, we're on board with that.
And I got a good people said okay yeah we're on board with that and i got a good
poll response uh for that uh i got a little bit of feedback from uh some of the national bodies
saying i'm not so sure about that because that's basically a pocket veto of the uh of the type id
uh function or operator because you have to include type info before you can use
type ID.
I agree and I don't think
that that's the right...
I don't want to sneak that feature
out of the language. I want to go through the right channels
for that.
For the paper that I
presented in Jacksonville, R1,
it's just additions
and the removals will come later.
I've started working on a paper for that.
And at least for the Albuquerque paper,
I was kind of in this weird double-think headspace
where it's like, okay,
I'm not removing exceptions or type info,
but if you weasel your way in just right, you're not ever
going to have to worry about exceptions or thread local storage or any of those things.
And after the Albuquerque meeting, I kind of decided, you know what, let's stop pretending.
And so one of the paper that I'm working on is going to make the bold claim that maybe we should make dynamic exceptions,
and not the new stuff from her, but dynamic exceptions.
Maybe we should make that optional and freestanding, because that's pretty much what people do.
And so, yes, it's probably going to be a
controversial paper when I pitch it, but
that's
basically
I want to go down the path of, let's stop pretending.
Right.
I want to interrupt the discussion for just
a moment to bring you a word from our sponsors.
Development of qualitative software
is impossible without the use of static code
analysis tools.
These tools enable you to detect code vulnerabilities and ridiculous typos.
By the way, many developers tend to underestimate the typos issue.
That's why we suggest reading the article, The Evil Within the Comparison Functions.
One of the most powerful static analyzers is PVS Studio.
This tool detects errors and potential vulnerabilities in the source code of programs written in C, C++, and C Sharp.
It works in Windows, Linux, and macOS environments, and it conveniently and easily integrates into the Visual Studio IDE versions 2010 to 2017.
Try the demo version of PVS Studio and find errors in the code of your project today.
So it sounds like with the exception of exceptions, the paper is mostly about what you're trying to add to what belongs in freestanding?
Yes.
So let me pull up my paper real quick.
Let's see.
So let's see.
Lots of stuff that's getting added.
Adding random stuff from C that wasn't there.
I mentioned ABS and QSort and Bsearch and crazy things like that.
There are weird things that get added
that you wouldn't necessarily expect.
Like if you want tuple,
so there doesn't seem like a reason
why you wouldn't have tuple.
It's just a really weird way of defining a struct.
But in order to pull in tuple,
I need to get some of the allocator machinery.
Not allocator themselves,
but stuff like uses allocator and allocator traits.
I have to pull in some of that.
But that's weird,
but that's all compile time, so that should be fine.
I think most people
aren't even aware of the fact
that tuple is allocator aware, and that
adds, what, like doubles
the number of constructors that it would otherwise
have or something.
In Albuquerque, I wasn't aware either.
Someone mentioned that to me, and it's like, oh, crud.
Let me go and look through that.
There's been a number of those kind of surprises as I've gone on.
So A2I, for instance, for a while I thought, oh, why wouldn't you include that?
Well, A2I is implemented in terms of is space in order to get past the leading spaces
and is space is locale aware
because there are different ways
of having spaces
in other languages, I guess.
And so that would pull in
a lot of locale stuff
and globals
and thread local storage.
And so A2I got booted to the curb.
Let's see.
In my latest revision of the paper, I've got variant in there.
I've got unique pointer, and I'll talk about those.
Those were some contentious things from Jacksonville.
Optional is there, but I remove the functions that would throw exceptions.
And the same is true
for variant as well. So like
variant, the dot
value, or sorry, git
on variant can throw an exception.
So I don't have git.
You can still call git if.
So the only reason git can throw an
exception is because of this
empty by exception that was
a huge controversy in the first place.
Is that right?
That's the reason that visit can throw,
but Git, if you give it the wrong type,
if you give it the non-active member, it can throw then as well.
Right, okay.
Whereas Git if will just return a null pointer
if you chose the wrong member union item.
I can't remember the technical term of that.
Similar kind of thing for optional,
where optional value can throw if it's in an error state.
So instead you can still use operator star and operator arrow.
And it's interesting because almost all of these have a more declarative alternative that I don't see a lot of people talking about.
Like, forgive me, I don't remember the name of it,
but something like get else or something like that,
where you can say two different paths,
like do it or return some default value, something like that.
Yep, and all of those are still present because they're useful and they don't throw exceptions, so why not?
So there's some other weird things that you wouldn't think would be a problem
but turn out to be a little bit of an issue.
So bit set, for a while I didn't have it in there
because even though it doesn't seem like it while I didn't have it in there. Because
even though it doesn't seem like it,
it doesn't seem like it should.
It has a dependency on stud string.
So
bit set has constructors that take
a string. Oh.
And the string can have like
ones and zeros in it, and the bit set
will be constructed with that. Okay.
Set, reset, and flip can all throw
exceptions. They're all range checked.
Given that I've got other container-ish
things where I remove some functions that
aren't critical for using it, I finally just decided, okay, fine, I'll have
bit set and remove five or six functions from from it a little bit more than i want but it's it's still usable i
couldn't say okay i'm willing to take stood array despite these functions and then exclude bit set
so in there i'm sorry if you don't mind i would like to dig into bit set a little bit because i
just had a conversation with someone how most of the functions that you just mentioned, except for the ones that take std string, ones
that could throw exceptions, they can all be constexpr. And if they were to throw an exception
at constexpr context, and that's fine, the program's just ill-formed, and it won't compile.
So where's this line where things that, if constexpr gets applied through bit set,
which hopefully it will for C++20, there's now a line like, well, if you use this in constexpr
context in your freestanding thing, then it's fine because it's impossible that it could have
ever thrown an exception at runtime. But you're going to remove the functions because they might
have thrown an exception if it had been used at runtime. It is an excellent point, and I've got an even
better example. This is some work in flight, so you may be familiar with constexpr all the things.
I am slightly familiar with it, yes. So some of the work in the standards that is coming out for that is they want to add constexpr containers.
Yes.
And the way constexpr containers are specified to work is that they hook into std allocator.
std allocator is not freestanding suitable at runtime.
So I would really like there to be a way to say, if this is used at compile time, go to town.
If this is not used at compile time, please give me a compile error
or a link error or something. And right now there isn't a way to do that.
But I really want that to be there.
So David Stone has a paper in the Rappersville
mailing. It is a
way to where you can overload on constexpr.
And I
think there's another paper
with a lot of famous
names on it, but I'm blanking on it right now.
I'm pretty sure Richard Smith and a few others are
on there.
To have a constexpr bang
keyword
that says, this thing must be constexpr bang keyword that says,
this thing must be constexpr,
but I don't think that allows for overloading.
I think you'd have to have a new function with its own name
that'd be constexpr bang.
So it's something I'm looking out for, and I want it to happen,
but it's out of scope for this paper.
Yeah, there's several people that have commented that, you know,
algorithms that you, you might want to implement an algorithm a different way if it's in a
constexpr context than you would if it's in a runtime context, that kind of thing also. So
I do think at some point we're going to ultimately end up needing a way to overload or Sphenae or
something based on if it's currently in a constexpr context.
Right, right. And there's at least one other paper on that that's some, it's not constexpr if,
but it's something like, you can check in your template function whether it's in a constexpr
context, or you can check within your constexpr function whether it's actually running at
constexpr. So there's a lot of different avenues that people are looking at for this,
and hopefully one will get chosen that helps solve my problems too.
Yeah, so ultimately what you need for the freestanding, if I understand,
is a way to remove a certain function if you're not in a constexpr context.
Absolutely, yes. I just don't want the
runtime version to be there at all right now if you don't mind i also would like a little bit of
a historical context because you're talking about freestanding as it currently exists but
where is that specified currently is that part of the official c++ standard yes it is part of
the official c++ standard uh if you look for the word freestanding, it shows up a dozen or so times, and there's a table that says which headers are there, and for the most part it just says all of these headers are there except for CSTODLIB, and CSTODLIB, a very small portion of that header is there. And there are a few places where it mentions core language things
that are a little different for freestanding,
but there's not a whole lot of mention of it.
For the most part, all of the language minus a very tiny amount
is there in freestanding,
and none of the library except for a very tiny amount
is there in freestanding.
So it doesn't get mentioned all of that much.
The only reason I even know about it was there was a Grill the Committee where Beeman Dawes mentioned it at one point.
And then I start – and he was basically saying, yeah, and the British Standards Institute, the British National Body, they care about it a lot.
And so I started Googling for it, and I saw one paper by Dan Sachs mentioning it.
And he mentioned some of the problems with it, like mem copies not there.
And this seemed like, yeah, this is a problem that I've had to work around for a while.
So that batch of things kind of inspired me to write a paper to say,
it's like, yeah, let's actually try to solve things
for embedded and kernel developers
instead of having them muddle through
with non-conforming C++.
So has it just not been given enough attention?
You're saying all these new features,
the standard library just doesn't mention it at all.
Have the committee just not been paying enough attention into deciding what should go into the freestanding implementation?
There hasn't been a whole lot of attention.
There have been a few people that have kind of watched over it.
But the use case that people actually seem to be using freestanding for is what I'll call the STL port use case. So there are a few
different small or private implementations of the STL that are hosted implementations,
but they kind of need to use some of the platform specific bits that come from the compiler. And so what those people will do is they'll try to
only use the freestanding parts of the host compiler
in order to implement their hosted implementation
of the STL. So STL port will do weird
tricks to include the
new header and the exception header
to get those particular types from the host compiler,
but then they'll implement their own std vector on top of that.
So the freestanding library does a decent job of satisfying that use case.
But the standard doesn't say that's its use case.
And I think there's more people that get benefit out of it if it did what it said that it was going to do,
rather than if it satisfies the STL port use case.
So do all compilers right now support some freestanding flag
that just none of us are aware of to put it in this mode?
GCC, or I guess I should say Libstd C++, supports it.
It doesn't get a whole lot of use
since it isn't particularly valuable right now.
Lib C++ does not have it,
and the Visual Studio implementation doesn't have it.
I don't know if Dinkumware has it.
If someone else, if Dinkumware,
it would not surprise me if Dinkumware has it.
There was this thing back in the 90s
called Embedded C++,
and Dinkumware had an implementation of that.
And so, yeah, it would not shock me if they had such a thing.
So if you're an embedded developer and you're using one of those compilers that doesn't have a freestanding flag, what are you doing right now?
Do you just need to avoid the features that you know aren't available?
It depends upon exactly which compiler you're using and which things you're trying to use. So if you're using GCC or Clang,
for the most part, you just take the hosted stuff,
and if it doesn't compile or link,
then you probably shouldn't use that,
but you kind of guess and check.
You'll find out you call, like, std stable sort,
and all of a sudden you start getting... well, one, your binary gets huge, and two, you might start getting linker errors that sbreak or mmap aren't present because stable sort can allocate behind the scenes. And you see, hopefully you didn't write too much code in between compiles there, so you know what actually changed and what went wrong,
because it's really hard to go backwards from,
oh, S break isn't there, to, oops, I called stable sort.
Embedded developers currently build with a lot of flags
that make their tool chain not conforming.
They'll turn exceptions off, and they'll turn RTTI off,
and they'll say RTTI off and
they'll say F no thread safe statics because there's not a general purpose way to implement
thread safe statics if you don't know how to spell mutex. Right, so this was the magic statics that
you mentioned earlier. Yes, so with GCC and Clang,
so things following the Itanium ABI,
there's an entry point, something
like CX ABI
lock guard,
or guard lock, or something like that.
And someone
can, if you don't have
that,
then you're going to get a linker error.
Someone could implement that on their own, and that's a reasonable thing to do
if you have a reasonable strategy for implementing it.
But that's a little bit higher burden than a lot of embedded developers are willing to jump through.
With Visual Studio, the code that is emitted directly deals with TLS
as opposed to handing it off to some other function.
So there's not really an opportunity to use thread-safe statics when using Visual Studio to target these environments.
So you've got to put those flags in if you want to keep on working,
and people do it and they're successful with it.
People use C++ and embedded
in kernel environment uh it's just they're not technically using c++ they're using non-conforming
c++ so i'm curious do does threading actually ever come up in like the kernel and embedded world? In the kernel world, absolutely. Okay. It is, you have to do mutex stuff
on a fairly common basis.
You can launch threads,
extra worker threads in the kernel.
You very often have to synchronize
against interrupts,
and that's not threads,
but it's similar.
It's still concurrency.
Okay. And then in the embedded space, it depends upon how big embedded you're talking about.
So that 512-byte target that I was talking about before, it has a real-time operating system on
there, and so there's a way to spell mutex that is
very different from the way you spell it
on Linux. So
we could have done something there.
Implemented CXA
guard acquire or whatever.
We didn't.
It was easier to just turn it off and not
use function
local statics.
Which I'm guessing is probably mostly unnecessary in that system anyhow.
Mostly.
A lot of the things that you can't do are things that are probably a bad idea anyway,
but not always.
And a goal of all of this is to try to provide a target for library writers.
So that way they say, okay, if I stick to the freestanding subset, I can have more customers for my library. So for example, most embedded
spaces, it's fine to use a compression algorithm. That's just math and memory access. But depending
upon how a compression library is written, it may or may not be suitable for an embedded environment.
So it'd be really nice to say, these are the things you can use, and if you use just those things,
then you can advertise that this library is freestanding compliant or something along those lines.
But right now, you could do that that but it wouldn't be a useful
advertisement because you could still
throw exceptions and such and
technically be freestanding compliant
so how
would your proposal affect
the community how would it affect like compiler writers
how would it affect
library writers
so the proposal that's out there right now
shouldn't really do anything to compiler writers,
but it'll do a lot to the library implementers.
Okay.
Basically, they would need to add a maze of if-defs
to accomplish this.
And I have asked around,
particularly I've asked LibC++ and LibStudC++,
if someone were to,
if my paper got accepted and put in the working paper
and someone submitted a pull request
that had this maze of if-defs,
would you be willing to accept it and maintain it?
You know, assuming all the caveats,
if it's well-tested and all of that.
And I got decent responses from that.
It's like, okay, probably, or absolutely yes,
depending upon who got asked.
I have no idea how to phrase that question to Microsoft,
because basically it's like, okay,
it's more of an ask my boss question.
So I haven't heard strong objections,
but since it'd be a one of many conforming modes,
I don't know that they would necessarily do it.
It's entirely up to them,
and they can still claim conformance
whether they do it or not, and
that's okay. Well, I haven't spent really any time in the Visual C++ standard library,
but they don't have as strict conformance switches as Cling and GCC or Libstd C++ and Lib C++
support. I mean, with GCC today, you can still go back to C++ 98, 11, 14, 17, 2A, whatever.
And if you've looked, well, you have, obviously,
but for our listeners,
if you look at the standard library implementation,
they already have this maze of if-def's
where certain functions are constexpr.
If they are constexpr in that particular standard,
they may or may not exist.
They may not have a return value,
depending on which particular standard the switch is set for at the moment yes and so this would be adding yet another layer and so i'm doing what i can to make it to where it's not hard to where
it wouldn't be a complicated if def uh to where it's like okay uh in freestanding mode, it's more about whether the whole thing is there or not for most things.
Right.
There's one place where I kind of had to be a little bit nastier, and that's with Unique Pointer.
So Default Deleter is a default template argument for Un pointer today. So in my paper, I
changed that around a little bit to where in freestanding mode, it is
implementation defined what that default template parameter is.
And if you don't, basically if the user doesn't provide
if they use the default instead of providing their own
deleter, then it's ill-formed.
And there's probably other ways I could say that,
but the goal there is to let people use UniquePointer with non-memory resources,
and if they use it with a memory resource, it is up to their implementation whether that works or not.
That was the best way I could think of to break that dependency on default leader.
It does seem like something that would need some good diagnostics
from the tool chain to let the user know,
by the way, this thing has changed meaning potentially
because you've compiled with a different flag now.
Right, and so one of the reasons I worded things that way
is so that you could provide,
so that way the default could be something
kind of like the way old static asserts were authored
before static assert was a thing,
to where you would have a template function
that isn't ever defined,
or sorry, a template class that isn't ever defined,
but just declared,
and you can give that template function
a really awesome name like
struct you used unique pointer
but didn't provide a default template argument T.
And so if they use that,
then the error they get out the other end
kind of tells them what they're doing.
That's up to implementations to decide how to do that.
But the other reason I kind of went down this path
was during C++ 14 or 17 standardization,
I don't remember,
they wanted to change the default parameter of std map to have
transparent comparators
so that you could compare
char stars and std strings
without having to construct temporaries.
When they first put it in, it's like, this totally doesn't
break ABI changing the default parameter.
And then a few months later, it's like,
oh, this totally breaks ABI.
Oops. So they had to kind of wind
it back.
So I was very hesitant to actually change the default template parameter.
Instead, I just give the implementation license to do so.
Okay.
So I think you mentioned that Odin's going to be presenting the next version of this paper at Wrappersville.
What changes are you still working on for the paper?
Well, it's in the mailing now. So R2 is there.
But I'm not going to Rapperswil. I try to limit
the amount of travel I do
to about two trips a year. And so
I'll be going to San Diego, so the meeting after Rapperswil.
But Odin graciously volunteered to champion this paper there.
But yes, this version of the paper adds unique putter.
It adds variant visit, which can throw if you're in the valueless by exception state.
But if you don't have exceptions, then it's really, I think it's impossible to get in that state if
there are no exceptions.
Let's see.
What else did it add?
It had to rebase to the newest
standard because
the
stuff is constantly moving.
So let's see. I had to add span
because that went in in between my last revision and this revision.
So keeping track of the—I really hope this goes in soon, not just because I want it there,
but because then I don't necessarily have to update it with every single working paper revision that comes out.
Because, yeah, it's difficult to track the diffs and all of that.
Yep, so those are the big things that ended up changing so it's the paper or the the standard that you're proposing
um going to have like specific guidelines so like when when we get networking or whatever in the
standard will it just automatically like the rules that are set forth would automatically
say what has to happen to networking or
just the fact that it wouldn't be included or something?
So those
rules wouldn't go in the standard.
They would...
I don't have
a place to put these guidelines
right now.
Other than word of mouth and
attending the meetings and telling people,
please put this in freestanding or remove it from freestanding. There has been some precedent for
that kind of rule setting. And so it would make sense to have a standing paper that says,
okay, these are the things that have these characteristics are freestanding,
things that don't are not freestanding, but currently that doesn't exist.
Okay.
But yes,
it'd be awful nice for that to be there and for the committee to have a,
a firm enough understanding to where I would not have to be the one person to,
uh,
to,
to watch that all the time.
Right.
Okay.
Well,
we look forward to,
uh, seeing how the paper does in Rapperswil with
Odin presenting it. Um, where can people find you online, Ben? Uh, so the easiest place to get ahold
of me is going to be on the CPP Lang Slack, uh, uh, community. Uh, I'm easy to find there. I'm Ben.Craig and I'm pretty active there.
Otherwise, email me
but I'm not really on
Twitter or any of that
but Ben.Craig at gmail.com
is a great place to get a hold of me.
Or, yeah, like I said, Slack.
Okay.
Well, it's been great having you on the show today.
It's been fun to be here.
Thanks for joining us.
Thanks.
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.