CppCast - Freestanding Proposal

Episode Date: May 17, 2018

Rob 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)
Starting point is 00:00:00 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
Starting point is 00:00:51 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
Starting point is 00:01:50 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.
Starting point is 00:03:00 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
Starting point is 00:03:26 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,
Starting point is 00:03:42 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,
Starting point is 00:04:13 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.
Starting point is 00:04:43 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
Starting point is 00:05:23 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.
Starting point is 00:05:48 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.
Starting point is 00:06:12 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.
Starting point is 00:06:29 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,
Starting point is 00:06:44 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.
Starting point is 00:07:25 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
Starting point is 00:07:50 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.
Starting point is 00:08:15 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,
Starting point is 00:08:36 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.
Starting point is 00:09:10 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.
Starting point is 00:09:37 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
Starting point is 00:10:09 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,
Starting point is 00:10:49 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.
Starting point is 00:11:31 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.
Starting point is 00:12:12 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
Starting point is 00:12:32 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.
Starting point is 00:13:13 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.
Starting point is 00:13:42 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
Starting point is 00:14:00 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,
Starting point is 00:14:25 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
Starting point is 00:14:55 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,
Starting point is 00:15:30 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,
Starting point is 00:16:13 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
Starting point is 00:17:15 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
Starting point is 00:17:55 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.
Starting point is 00:18:23 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,
Starting point is 00:18:51 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.
Starting point is 00:19:15 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.
Starting point is 00:19:36 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.
Starting point is 00:20:26 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
Starting point is 00:20:59 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.
Starting point is 00:21:16 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?
Starting point is 00:21:43 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,
Starting point is 00:22:15 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,
Starting point is 00:23:17 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
Starting point is 00:23:40 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.
Starting point is 00:24:35 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
Starting point is 00:25:07 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.
Starting point is 00:25:23 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
Starting point is 00:25:39 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.
Starting point is 00:25:55 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.
Starting point is 00:26:35 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.
Starting point is 00:27:20 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
Starting point is 00:27:37 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.
Starting point is 00:28:20 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
Starting point is 00:29:00 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
Starting point is 00:29:19 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,
Starting point is 00:29:42 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
Starting point is 00:30:27 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
Starting point is 00:30:44 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.
Starting point is 00:31:28 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.
Starting point is 00:31:54 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.
Starting point is 00:32:15 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
Starting point is 00:32:32 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?
Starting point is 00:32:56 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
Starting point is 00:33:18 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
Starting point is 00:33:47 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
Starting point is 00:34:02 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
Starting point is 00:34:21 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,
Starting point is 00:34:59 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,
Starting point is 00:35:28 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.
Starting point is 00:35:44 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
Starting point is 00:36:22 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
Starting point is 00:37:08 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.
Starting point is 00:37:56 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.
Starting point is 00:38:16 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
Starting point is 00:38:33 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.
Starting point is 00:39:07 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
Starting point is 00:39:47 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,
Starting point is 00:40:39 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.
Starting point is 00:41:21 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.
Starting point is 00:41:43 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
Starting point is 00:42:36 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,
Starting point is 00:43:16 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.
Starting point is 00:43:47 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?
Starting point is 00:44:16 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,
Starting point is 00:45:06 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
Starting point is 00:45:39 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
Starting point is 00:45:59 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.
Starting point is 00:46:36 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.
Starting point is 00:47:16 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
Starting point is 00:47:45 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
Starting point is 00:48:01 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
Starting point is 00:48:41 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
Starting point is 00:49:14 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.
Starting point is 00:49:34 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,
Starting point is 00:50:04 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,
Starting point is 00:50:26 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,
Starting point is 00:50:52 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,
Starting point is 00:51:22 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
Starting point is 00:52:11 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.
Starting point is 00:52:51 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
Starting point is 00:53:15 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
Starting point is 00:53:34 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,
Starting point is 00:54:00 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,
Starting point is 00:54:20 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?
Starting point is 00:54:44 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.
Starting point is 00:55:20 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.
Starting point is 00:55:42 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
Starting point is 00:56:26 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.
Starting point is 00:56:41 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,
Starting point is 00:57:09 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,
Starting point is 00:57:23 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
Starting point is 00:57:54 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++.
Starting point is 00:58:08 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.

There aren't comments yet for this episode. Click on any sentence in the transcript to leave a comment.