CppCast - system_error and Boost Outcome Review

Episode Date: June 21, 2017

Rob and Jason are joined by Charley Bay from F5 Networks to talk about his recent CppNow talk on system_error and the Boost Outcome review. Charley Bay is a Software developer at F5 Networks w...ith 25+ years experience in large-scale and distributed systems for low-latency C and C++. News C++ Web Frameworks Full Http/WebSocket Server framework using Beast and Boost.Asio Quick-Bench.com Simple Online C++ Performance Benchmark Turing Tumble Kickstarter Charley Bay Charley Bay Links C++Now 2017: Charles Bay "C++11's Quiet Little Gem: " Boost Formal Review Process Boost Outcome Boost Outcome Review Report Sponsors Backtrace Hosts @robwirving @lefticus Better C++/Chicago

Transcript
Discussion (0)
Starting point is 00:00:00 This episode of CppCast is sponsored by Backtrace, the turnkey debugging platform that helps you spend less time debugging and more time building. Get to the root cause quickly with detailed information at your fingertips. Start your free trial at backtrace.io slash cppcast. Episode 106 of CppCast with guest Charlie Bay, recorded June 21st, 2017. In this episode, we talk about a new online compiler tool. Then we talk to Charlie Bay from F5 Networks. We talked to Charlie about system error and the boost outcome review. Welcome to episode 106 of CppCast, the only podcast for C++ developers by C++ developers. I'm your host, Rob Irving. Joining me is my co-host, Jason Turner.
Starting point is 00:01:21 Jason, how are you doing today? I'm doing good, Rob. How are you doing? I'm doing pretty good uh y'all ready for the chicago event uh mostly mostly still getting ready yeah it's a few weeks away now right uh yeah yeah i've got plenty of time it's uh july 12th is the first day okay cool and no real news with me i'm. I'm just starting to enjoy the summer, although we're getting a lot of storms out here. Oh, I wish we were getting storms.
Starting point is 00:01:48 It's like 96 today. Oh, that's rough. Anyway, at the top of our episode, I'd like to read a piece of feedback. This week, we got a comment based on our discussion last week in the feedback where we're talking about the website. Vipple wrote in, open source C++ web frameworks
Starting point is 00:02:08 and he's got a link to Wikipedia here. Interviewing their contributors might lead the podcast to a better CMS solution than Node, NPM, and Sass. You guys beat me to half unconsciousness in the first five minutes of this last episode with all of those missile IDs.
Starting point is 00:02:28 Vipple, i apologize for the uh the node and npm discussion last week i promise it's not going to be a frequent topic of discussion but the website is fully fixed now um good it's good including the the mobile site i got that resolved despite the fact that you're not a web developer despite the fact i'm not a web developer i i struggled through I'm not a web developer I struggled through it I did take a look at this Wikipedia page which is a comparison of all well not all but lots of different web frameworks
Starting point is 00:02:54 and it's broken up by programming language so it does have four entries for C++ we've talked about Poco before although I don't remember discussing it as a web framework, but I guess it does have an HTTP library as part of it. Um, I quickly looked into some of those, some of these other ones, CPP, CMS, TNT net and
Starting point is 00:03:16 WT, which I think is supposed to be kind of like a web QT. Um, so some of them looked interesting. It's just not necessarily what we need for CppCast because we don't necessarily care about high performance or being able to run unembedded devices, which is what some of these are kind of meant for. We just want a simple web site that doesn't take too much for us to run. Yeah, you just yeah it just compiles it and post every time you we post something new right i mean it needs to be as simple as straight as possible yeah if someone made a c++ static website generator that ran off markdown files i would switch in a heartbeat but there might be one out there i know i've had conversations with people about this kind of
Starting point is 00:04:04 thing but i don't know the status is yeah we definitely don't want to rewrite everything There might be one out there. I know I've had conversations with people about this kind of thing, but I don't know what the status is. Yeah, we definitely don't want to rewrite everything in C++, though. But if we could use a C++ tool, that'd be great. Anyway, 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
Starting point is 00:04:25 is Charlie Bay. Charlie is a software developer at F5 Networks with 25 plus years of experience in large scale and distributed systems for low latency C and C++. Charlie, welcome to the show. Hello, good to be here. All right, Charlie, 25 years of C and C++ experience, that's a pretty good swath of experience there. Yeah, well, you know, back in the late 80s, it was a lot of C. C++ was only just getting started, right? So then in the early 90s, it was sort of, hey, there's this C++ thing, and it's got destructors, and it's deterministic, and we should play with that. And so I've always kind of been a bare metal hardware guy.
Starting point is 00:05:03 I did a lot of embedded biomedical kind of stuff. And, you know, we turned our own board. So it was a lot of low level C stuff. But C++ ended up being really good for a lot of those patterns. So did you start using C++ then in the early 90s? Yeah, in the early 90s. Wow. And in production code?
Starting point is 00:05:23 In production code. You know, it was, you know, back then there was, you know, it was a lot richer. Well, richer. It was a lot more diverse environment, right? Because portability was kind of an issue. You had the segmented memory models. I mean, you know, you and Godbolt, and, you know, a lot of people have talked about the good old days. But, you know, frankly, it's not good to revisit some of that stuff.
Starting point is 00:05:42 Just let it go I remember it was really interesting back when Microsoft's 03 compiler started to usurp the Borland version 5 compiler which is a great compiler, Borland was doing awesome and all of a sudden these new toolchains started showing up and they've just gotten better
Starting point is 00:06:00 ever since, back then it was often hey, my code's right, the compiler's wrong and you were right a lot of the time and better and better ever since. Back then, it was often, hey, my code's right, the compiler's wrong. And you were right a lot of the time. Now it's kind of the opposite. Your code's wrong. It's almost always your code's wrong now.
Starting point is 00:06:15 I mean, there are compiler errors, but that bites such a small percentage of the real world. Yeah, they tend to be quite esoteric, I think. Yeah. Yeah, so I think that revisiting stuff back in that day, like even shortly prior to that, where you manually did your linking by hand, you know, you don't trust these linkers.
Starting point is 00:06:34 Those are crazy. You would do that by hand. Well, you don't really want to go back to those days. I mean, there's no good stuff to talk about back then. It's interesting, but, you know, don't. So you've basically followed C++ for its entire commercial lifetime, pretty much. Oh yeah, yeah, yeah. Cfront, I never really used Cfront, but the compilers, you know, all of them, the commercial ones on up, I've played with all those. And, you know, nowadays
Starting point is 00:07:02 we have such really, really good options. I mean, the Clang GCC, the Intel ICC compiler, and then, you know, Microsoft's compiler is really doing some awesome stuff. There's really, really great advances. And, you know, now we mostly don't have to worry about these cross-platform portability problems. I mean, you can if you're bleeding edge and doing tweaky things, but most developers, they've really got it good now. Write good code,
Starting point is 00:07:29 make it clear, it will port, everything will be correct. It's funny because you start working with some of these new grads and they're not exposed to some of this esoteric burn yourself on the stove stuff. I've got brain cells and neurons and pathways in my head that's devoted to this useless information. And, you know, I'm not sure that somebody starting
Starting point is 00:07:54 out today should really know any of that stuff. It's not really relevant anymore. But having gone through all this, I know some people like loved the simplicity of like borland turbo c++ with its 2e interface like is there any piece of it that you say i miss how x compiler back in 2003 worked or i something is there any piece well not really mostly it's it's i've uh i've been surprised at how my personal style has evolved. Because even though I've done it a long time, you think that, okay, well, you're done evolving. Well, no, not really. I mean, C++11, we all know that's all different. And Lambdas is changing how we do things. And Code Constructs, the structured binding thing coming out with 17, that's going to change how we do things but you know it's even the simple stuff you know i've changed uh just in the last few years my my attitude on you know
Starting point is 00:08:50 placement of const and how to name things and you know that there is some stuff that is still forcing you to evolve but you know back then anything that you're sort of admiring like the edlin one line editors and you know it's it's You can call it the glory days, but really it's just a waste of time, largely because I remember when Borland came out, I think Borland version 5 compiler, they were the first ones to come out with colored highlighting. And prior to that, you look at code on the screen, it's all one color. And then there's this colored highlighting,
Starting point is 00:09:21 and I thought, well, that's really offensive to me because real programmers should not need to see syntax highlighting on keywords. I mean, you should know that's a keyword. And well, after a couple years of that, I decided that was a good idea. I think being open to change and evolving to best practice, it's surprising the little helps. Like right now, I tend to run, I do a lot of Vim still,
Starting point is 00:09:49 but when you run an IDE and you have a spell checker, you think, well, you don't need a spell checker. This is code. It compiles, you know. Well, a spell checker is pretty nice to have in code, comments or otherwise. So even seemingly stupid, unrelated things like a spell checker, it really ought to be part of the modern day coded environment. That was never even a dream back then. You'd never think about that.
Starting point is 00:10:17 Okay, Charlie. We're going to talk about a couple news articles we have here and then we'll start interviewing you about your work on the outcome library, system error, anything else that you find interesting okay great okay so this first article we have is that uh we talked about beast again recently they're going to go into a boost review pretty soon and they just announced uh vinnie falco the author of beast that they made a full hdp and WebSocket server framework based on Beast and Boost ASIO, and that's now available for testing. So, you know, we were just talking about those C++ web frameworks.
Starting point is 00:10:53 Now Beast is another option there. Yeah, and it seems the Reddit comments that we discussed last week were complaining, basically, like we need some higher level something, not just this intermediate level beast thing. So, well, here's the full example. I've been following beast for a long time. The author is
Starting point is 00:11:15 very ambitious and active and he's very current with some of the latest language changes. I'm a huge beast fan. I think this is a great library. It's almost it you know, it calls itself a framework. And that's where it starts to get interesting, right? Because anything that gets to the level of a framework, you're adopting, you know, a paradigm and a use model and other parts of your modules will have to adapt to this thing that's at the scale of a framework. So I'm a huge
Starting point is 00:11:43 fan. I think we need more of this, but it's always a challenge when you use that word framework on any kind of submission. Right. So have you actually utilized Beast yourself yet? I've not, but there've been several past projects where if it were available,
Starting point is 00:11:59 I would have picked it or it would have been a strong contender to be picked because I think it's serving a real good niche and I like the way he's approaching the problem. But, you know, like everything else, the APIs are highly variable. I mean, it's like the ASIO thing. Do you want to go ASIO?
Starting point is 00:12:13 Once you go with the proactive model, you know, that sort of modifies how you think about it, it structures all the code around your use of it. So you just have to adopt the metaphor he's presenting, which I think is actually a very good metaphor, but there's a lot of devil in the details on that kind of it. So you just have to adopt the metaphor he's presenting, which I think is actually a very good metaphor, but there's a lot of devil in the details on that kind of stuff. And if you don't mind, if I take a slight diversion, you work for F5 Networks. Have you guys adopted ASIO internally? Is that something you can talk about at all?
Starting point is 00:12:39 We are a Boost user. I think that's public knowledge and uh you know boost is a great library it's it we have a large legacy code base you know there's new code bases too so um yes there's there is you know like like all large large products so for anybody who doesn't know you know application delivery controllers network traffic processing that kind of stuff um we have a lot of code and some of it is coupled to Boost. We have other languages, too. And Osio, we are using it. Boost provides a lot of good stuff. Osio provides a lot of good stuff.
Starting point is 00:13:12 So for the low-level data plane traffic, that's all handwritten, right? That's internal. But libraries like Boost just help you get work done. So, yes, we're a user of Ozzio and Boost. So are you looking forward to Ozzio potentially becoming part of the standard networking TS? I am. You know, it's, you know, Ozzio is, you know, it's the networking TS, right? And it's kind of like the file system TS. You know, they're kind of built in the same frame of mind for how you're going to start working with these either callbacks or some kind of asynchronous problem space where you're trying to budget your design for handling delays, right?
Starting point is 00:13:58 Some of these are very long delays. And I like them because they are solving in a clean way a problem that should be a solved problem. You can't write this stuff out of the box for every new project. It's crazy. And yet at the same time, I think Robert Ramey's observations on the general scale of, well, Ozio is a big piece of work. It's a big work. And is that a reusable library is kind of a separate question of is that an industry convention or an industry framework that people tend to use.
Starting point is 00:14:34 I think we're getting to a point where it is a little tricky, and I commend Robert Ramey for bringing up the thought, but it is a little bit tricky to figure out where does the standard end and where does industry convention begin and so networking is big file system is big as big as they are i i think they're um incomplete insufficient you need more and well well that makes big even bigger so you know what are you going to do with that that That's a challenge. It's an industry challenge, really. So this next thing we have is the Quick C++ Benchmark. It's at quick-bench.com. And the interface looks really similar to Godbolt to me, where you can just put together a couple of functions and quickly benchmark the output to uh to do comparisons and use i thought you're gonna say you know for different compilers but looks like currently it's
Starting point is 00:15:30 just clang and just clang 3.8 at this exact moment yeah yeah uh it's i've i spent uh maybe more time than i should have this morning playing with it. And I find it's great. I need now some sort of tool that will let me look at the assembly output on Compiler Explorer, then click a button and have it automatically run the benchmarks for me. That would be just spectacular. Well, whoever's making this, maybe he could get together with Matt Godbolt, do some collaboration where he could put the two tools together. It would be nice.
Starting point is 00:16:04 That would be great. So, Jason, question. When you ran it this morning, did you turn that show no-op bar on? Were you looking at the no-op measure? Because I think that's a great feature. No, wait, I don't even
Starting point is 00:16:19 see that. It's at the bottom of the benchmark graph, yeah. Oh, hey, that's neat's neat no i didn't see that okay yeah i've uh i really like that feature because um it helps you normalize the overhead of the test from what you're actually testing right so i found a surprisingly high amount of value and do you have a no op measurement and well shit this tool does that's kind of cool well in this particular example is a very interesting one because it should all fall into uh small string optimization that like the default example that comes up should fall into small string optimization and clang should be able to fold away like a shocking amount of it like this these benchmarks these timings must be really
Starting point is 00:17:06 really tiny that it's that it's comparing here yeah okay uh so the next thing we have is uh turing tumble jason you want to introduce this one from kickstarter yes you know i you know we've never like promoted something like this on here before and i'm not trying to say i'm promoting this kickstarter but i put it on here specifically because we have charlie as a guest today and it was in one of your your talk uh at c++ now uh 2016 that you mentioned touring trains i believe yes yeah i i was not aware of this Kickstarter. It's a, it's a,
Starting point is 00:17:47 it's a touring tumble. It looks like a, it's kind of like a kid's game. Yeah. Yeah. It's a marble game. The marbles fall and you have gates and they go left and right. You can compute and count in binary. I thought it was really cool.
Starting point is 00:17:57 It looks like a lot of fun. Yeah, it does. You know, it's, it's, it's always painful when you have to build that much surface area to get eight bits. Right.
Starting point is 00:18:09 But touring trains, kind of like little Lego things where they throw gates and you count and you do whatever. Well, shoot, that takes your whole living room floor. So there's a trade-off to make somewhere. Yeah. Can you describe the touring trains briefly for the people who are listening who did not watch your video? Oh, right. So, you know, it's an old idea. It's not my idea.
Starting point is 00:18:29 But people out of Legos have built, if you hop over to YouTube or anywhere, they've built all kinds of mechanical computers that basically, you know, a ball goes by or a train goes by and the gate flips. And, well, you can count and start building higher order logic off of that. And, well, you can do shifts and divides and multiple. You can do whatever you want. So everything the CPU can do, you can do basically with trains running around on the floor of your living room. It's just you have enough track and enough, you know, toys to play with. Like really, really slow-moving electrons?
Starting point is 00:19:02 Yeah, yeah. Although debugging gets easier. But, you know, usually, you know, kind of likemoving electrons? Yeah, yeah. Although debugging gets easier. Usually, kind of like bugs, or the bug physically crawled in there and shorted the circuit. Well, this is de-catting or de-dogging if it's a train on the floor of the living room. Right.
Starting point is 00:19:17 You have all kinds of mechanical maintenance, so you get to be a hardware guy in addition to a software guy. This reminds me, I once saw a youtube video where someone had built a simple adding machine in minecraft but it was you know gigantic in the scale of the world of minecraft but you know you have like kind of simple electrical circuit type things that you could light up with a torch or something like that and and using those he built this giant adding machine that you could fly around and use in Minecraft.
Starting point is 00:19:46 It's pretty cool. I can see a lot of value to anything in virtual space, because real-world space is highly limited. I think they've taken those Minecraft things all the way to the point of 6502 emulators. Like, crazy craziness. But yeah, back to this Kickstarter. It's only got a week to go, but they're already well past their goal. So it looks like this thing will be built.
Starting point is 00:20:17 And there's a little video you can watch to see how it works. And it looks pretty cool. And they're saying it's fun for adults too. It comes with like 50 different challenges and it looks pretty cool and they're saying it's you know fun for adults too some they've got it comes with like 50 different challenges uh that you can do using these uh this little marble game and these different little plastic kind of bit flips and things like that yeah they're already six times past their goal so yeah that'll be funded. Yeah. You should order one for your kids, Rob. I might do that. Okay. So Charlie, I think it was four episodes ago that we had Niall Douglas on talking about boost outcome. During the time we were interviewing him, he was still going through
Starting point is 00:20:57 the process. Do you want to tell us a little bit about how that went from your point of view? How many emails did he have to go through? What was kind of the final outcome of the outcome library? Right, yes. Okay, well, the process is complete. So the Boost outcome review, it is over. And, you know, it's a Boost review, right? So the outcome library was a tremendously successful review according to the Boost guidelines,
Starting point is 00:21:24 or according to the Boost community, what the Boost does. You know, this is my first time as a review manager. I'm usually a lurker. I'm in the community. I go to BoostCon, but, you know, I'm not really a library author. I have not gone through that process, but I stumbled across the library. I thought it was really cool. I contacted the author and said, hey, do you have a review manager?
Starting point is 00:21:44 And I volunteered, you know volunteered to take on that role. And it's basically public service, right? Usually when you're assigned community service, it's court ordered. In this case, I kind of volunteered to do it. But the library caught a lot of attention. It really hit a nerve. There were some 850 emails on the list that talked about the library. At the conclusion of the review, I read all those a second time because I had to prepare a review report on the conclusion. And there was a lot of discussion in a lot of
Starting point is 00:22:17 tricky areas. And I thought it was fascinating and interesting largely because of the volume of deep and well-considered thought on appraising what's it trying to do and how and what are the missed opportunities and what changes should be made. Is this thing – is it boost quality? So at the end of it, there was a lot of support because it was my first time. There was a lot of support on how does it work and review wizards. I think the documentation is really, really good. People can't step into this role. Largely, what was not discussed in the review, even in the 850
Starting point is 00:22:52 emails, was the reason why I volunteered to be review manager, which is in the documentation. If you go through and read through it, it talks about, now puts forward this idea of islands of exception in a sea of no except. And that really struck a nerve with me. That seemed like a very practical, manageable way to deal with error handling,
Starting point is 00:23:15 exception handling at scale across big systems, across module boundaries, third-party modules. And, you know, largely that conversation wasn't directly addressed in the review, but a lot of other things were, and substantive other things. So it was a great review because so much got covered. I think it hit a nerve because it's a need in the community. And in this particular case of outcome, what he's trying to do, what the library really does, is he provides a mechanism where you can have this thing called result. And the result is either the value you wanted or an error saying why you didn't get that value. It's kind of like a generalized form of stood accepted, right? We have stood optional coming in C++17. You get your T or you get nothing.
Starting point is 00:24:05 Well, std accepted, it's not in C++17. It's probably in C++20. There was a lot of discussion on that tied into the acronym review, but it's a generalized version of optional where you either get the T you wanted or you got these other things. Maybe you can have several other things
Starting point is 00:24:20 like different kinds of errors, exceptions, whatever you want. And that was done because if you can't have the T, well, why can't I have my T? Well, give me an error or give me an exception or give me something to tell me why I can't have my T because optional won't do that by itself. Well, outcome, the library, that's what it tries to do. I get my T or I get my error. And he has an outcome class. It's a T or it's an error or it's an exception. So, well, why do you have two? Because that was one of the questions on the list. Well, why do you have a result, which is T or error, or you have an outcome, which is T or error or
Starting point is 00:24:57 exception? And then, you know, insert 850 emails. Essentially, there's a lot of real world system constraints that are imposed regarding static checking and compile time or checking at runtime, you know, whether or not undefined behavior is a good thing, because it can be a good thing, because it's faster. If I don't have to do extra work to give you a wide guarantee. I'll give you a narrow guarantee. And if you do a no pointer indirection, well, that's on you. So these trade-offs when you deal with error handling, error handling is a very loaded problem. It tweaks a lot of people kind of in funny ways because you're talking about composition of APIs across third-party libraries. And that's a challenging, hard thing to do.
Starting point is 00:25:46 Well, that's what Outcome tried to do. And the library, I think, did an excellent job at saying, look, here's a tangible implementation that is high quality that will show you some multimodal operations where you can compose specific to the constraints of your system how you would like to handle exceptions, errors, or both. And, you know, in the end, I think the discussion was very productive. But in the end, of course, the library did get rejected for other reasons.
Starting point is 00:26:19 Well, do you want to go into why it was rejected? Yeah. So the rejected – so, okay, I am not an expert on being a review manager. I am very studied in this domain, which I think is an important and necessary requirement. And the BOOST guidelines say you have to know the domain to be a review manager. I would have voted to accept the library. But I'm, you know, in the role of review manager, there is discussion on a lot of topics. You weigh them and assess on the whole, is this going to be a viable good thing for the boost distribution? Because
Starting point is 00:27:02 we didn't miss opportunities. It makes sense. You know, the documentation, everything's up to quality of what's expected to boost. Well, in this particular case, I think it harkens back to every now and then, not always, but every now and then, you have a fundamental problem. And some of the approaches tend to be fundamental approaches or libraries or solutions where you sort of rethink this is the new best practice for the industry. So, for example, ASIO and the TS networking, TS for C++, it's not in there. How many years has this been going on? There's been talk and talk and talk, and yet it's not in there.
Starting point is 00:27:42 So is that a failure? Well, it's not a failure. It means we're still trying to figure out the sharp corner cases. How are we supposed to think about this? What is the best way to compose and deal with networking in C++ code bases, especially in light of these new language features, which are changing how we compose our algorithms, how we establish our public APIs,
Starting point is 00:28:05 and what is this vocabulary type, or even is there one, to transfer state, error state or exception state, across third-party boundaries that were not designed to talk to each other. So this, I think, is what Outcome stepped into. It is that. It is at that scale, and that's why there was so much discussion. So the rejection largely is based on we did have a couple of technical things that are important that were not at consensus at the end of the review. There were a couple other things that were maybe dealing with the library. It was perceived as setting precedent to changes to the boost distribution itself. You know, there's some CMake stuff,
Starting point is 00:28:46 and there was a dependency on a module that was external to boost itself. It had dual license Apache 2 and DSL. You know, there was enough coloring outside the lines that some of the reviewers were a bit – it challenged their ability to evaluate, well, am I evaluating a library or am I evaluating a modification to the boost distribution packaging and policies? And I think some of that cluttered it a little bit. So in the end, there wasn't enough community consensus for the libraries. It was rejected.
Starting point is 00:29:16 But I would have, if I were a voter, I would have voted to accept. It's just that we had enough people with well-reasoned, substantive thought on we probably do want some changes. And the author, Niall, he agreed. Yeah, there are some changes that he would like to do as a result of the feedback of the review process. The review process was highly constructive. There was a lot of information given on a lot of topics. And there was a bit of overlap with stood expected. It's not in the standard yet, but it's being proposed,
Starting point is 00:29:45 and there was maybe some discussion about how that might evolve. There was a lot of talk about Stood Variant, and it's got that empty by exception kind of thing going on, which is a little funny. And so there was talk about, well, could we have a variant two that did not have that edge case, that corner case? So Outcome, especially if it becomes a vocabulary type, it's kind of in the same area where do you want this thing to work with wide contracts?
Starting point is 00:30:11 Anybody can play with it and use it and they can't hurt themselves? Well, you're going to pay for that. Or do you want it with narrow contracts? And you have to use it just right or everything explodes and everybody dies. And you've got to kind of pick a direction. And one of the things that I think
Starting point is 00:30:28 that the Outcome Library did that was really, really good is there was a very clear contrast in... You know, I give credit to Niall for this, but he identified basically as single modal usage or multi-modal usage.
Starting point is 00:30:44 And that, well, you know, almost always you want to do the single modal usage thing, where, well, what's that? Well, you know, here's my library, here's my API. And, you know, this one canonical way, this is encouraged, this is understood, we can scale off this. That's a single modal thing. Well, every now and then, you get this multi-modal thing. And outcome was sort of forcibly pushed into this multimodal domain.
Starting point is 00:31:09 And that was, according to the author, was because we had different user bases with different constraints. Some of them wanted to compile with or without exceptions or with or without static runtime checking and with or without narrow or wide or, you know, other things dealing with runtime overhead. And what the outcome library did is, well, you know, if you want all of that richness where you can insert your custom error type with different behavior and different runtime constraints, different compile time guarantees, if you want to compose that and set it up, compile it, propagate through the framework and out your public APIs,
Starting point is 00:31:49 well, you can do that. But that does significantly complicate the design. And that's what the reviewers saw. They caught it and they called that out, saying, look, is this complication really necessary? Because, you know, a lot of the reviewers are saying, which is very legitimate, is, look, I don't want a complicated design. I want something simple.
Starting point is 00:32:07 I want, like, system error. System error is actually pretty simple. And the whole idea there is, look, I've got a thing. It stood, you know, error code. And I can pass that from my API to your API, and that just works. It's a type array, simple way that we all have a common understanding of what is the error state.
Starting point is 00:32:24 An outcome in a single modal design kind of on a c++ standards track perhaps evolving into something inserted in the system error in the future the header system error in the future well well that would be cool because i have an error an exception wrapper you're using the same one i don't have to recompile we can just relink or you know dynamically link at runtime and you know we you're using the same one. I don't have to recompile. We can just relink or, you know, dynamically link at runtime. And, you know, we're all using the same types. But if everybody can do their own thing, if everybody can compose according to their own system-specific limitations, well, you kind of give that up. So do you want a simple design, single modal standard track? Or do you want a complicated design, very user configurable,
Starting point is 00:33:07 very tied to your system-specific constraints? And Niall was very clear, low latency was a lot of what he was looking at. If you want to go low latency, it's kind of nice to have that power. And the outcome library basically was trying to give you that multimodal best of both worlds, but it's not going to give you the best of both worlds really. Because the single model design by definition is you got one, two types, they're simple, for the C++ community to talk about this error handling, exception handling thing. And I think in general today, for whatever reason, we do not really have consensus where, you know what, our current current libraries our current idioms our current practices that's sufficient it's good we got it we understand it i don't believe that to be true and an outcome really boy it really tried to lance that windmill and you know it's it's a tough one so so coming out of it though actually there's a lot of good things i mean there was enough
Starting point is 00:34:23 discussion there were some changes to hey we're going to make um these modifications design there is there is internal work in outcome i think it's production ready today you know i think people are using it today and now i could probably give you more more information about that but some of these changes that are underway based on the feedback they they're good changes. I mean, you want ideally a review process to be a review process. And it was. And that means I see what you did. I see the domain you're trying to address. Does this address that domain? Were there other ways we could have done this that maybe would have been better? And okay, specifically what you you did are there any missed opportunities you know if i tweak this or fiddle with that it'll scale better it'll plug in with these other things
Starting point is 00:35:10 better you know it handles these language features better um one of the things that i i never really expected i never thought about at the beginning of the read process that i learned along the way was well if you have a vocabulary type you you know, here's this thing, like stood variant is one, or stood optional would be another one, stood expected when it shows up, it'll be another one. Well, if it's a vocabulary type,
Starting point is 00:35:33 you know, you tend to want to provide guidance to users regarding how do you want to iterate on these things? How do you want to establish a visitor pattern that can safely interrogate and rip out the state from the variant that's relevant? And, you know, that's a design thing. You know, you have to decide that upfront and lay out an API where that'll work. And some of the discussion with outcome was
Starting point is 00:35:57 specifically on that topic. You know, how are people going to use and scale with this thing? And based on those changes, there's some internal implementation details that are going to change, but probably some API changes too, maybe a couple name changes. So from that standpoint, the review was very effective because the library author got good actionable feedback that the library author believes will make the library better. So it's the boost review. It's, you know, it's sometimes like Clash of the Titans. But, you know, it is a pretty fantastic thing that you have all of this outstanding brainpower dedicated to reviewing, you know,
Starting point is 00:36:43 essentially what becomes world-class tricky and complex problems in the face of what is current best practice? What are we bringing out with language features? How are you supposed to use, you know, even the C++ language standard itself? Right. So do you think once all of this feedback is taken into account and IOL makes changes to it, that it has a chance of actually being accepted. I do. I do. And you know, that's, this is kind of like the, um, you know, the networking TS, you can use Ozio now, right? Whether it's part of boost or not part of this, you can use it. Outcome you can use now, whether or not it's part of this. So, well, the networking TS would be
Starting point is 00:37:20 better if it was maybe in the standard. Well, you know, maybe that's true. So, well, it's just a TS, right? So you can use a TS, even though it's not kind of, kind of not in the standard. So outcome, you know, I think there is a, I think there is a question that we still have not answered. And I defer, you know, to the library authors in the future review, but do we want to go standards track? Or do we want to go to this multimodal user composable thing? Because they're probably a little bit in contrast with each other. So I am confident that the outcome library will evolve and it will go from a good library to an even better library. It may or may not make it into Boost.
Starting point is 00:38:04 I think it probably would with these changes and some of the other discussion. I think it would actually with these changes in some of the other discussion. I think it would actually be accepted in the booths. But, you know, I'm, you know, I got to fall back to Robert Ramey again a little bit in that the library as it is today, we concluded a review and it was rejected. And that does not mean it's a bad library. It doesn't mean it's not production quality. It means that the boost community couldn't figure out quite how it fit in and whether or not it did reach that level of, I understand it, these idioms are good, and
Starting point is 00:38:33 we are now recommending new best practice. We didn't really have that. Now, ideally, that's the bar we would reach. If it's a niche library, maybe it's not a big deal. But this isn't one of those. It's more of a fundamental thing. So I think another boost review, if it were to occur, it could be big and wild and contentious and back to narrow and wide contracts and all kinds of stuff in part because the questions I think for this particular library we're trying to answer is,
Starting point is 00:39:03 do we understand the idioms and are we experienced enough to make sensible recommendations about, yes, this is something that should be used in this way? Is that a niche thing? Is that a general thing? Is that a standard thing? And it's kind of hard to guess what's going to be in the next standard. And for the same reason, it's kind of hard to guess what the boost community will see as this is a well-understood, accepted practice where we're ready to endorse these idioms as okay. Because it is new idioms.
Starting point is 00:39:37 This is somewhat novel that you can get a T or an error back, or a T or an error or an exception back. And, you know, frankly, my selfish little interest is, I would like more discussion about this sea of no except, islands of exception in a sea of no except.
Starting point is 00:39:55 I defer denial for putting that thought forward, but I think that really is a, that is the closest I have seen us come to unifying errors are not exceptions they are different their composition patterns are similar sometimes
Starting point is 00:40:12 they're trying to do overlapping things but in our heads we have not separated them entirely and therefore we don't really have a vocabulary to talk about them so you know I don't know maybe that vocabulary is resolved, you know, I don't know. Maybe that vocabulary is resolved at the next review.
Starting point is 00:40:27 I don't know. I wanted to interrupt this discussion for just a moment to bring you a word from our sponsors. Backtrace is a debugging platform that improves software quality, reliability, and support by bringing deep introspection and automation throughout the software error lifecycle. Spend less time debugging and reduce your mean time to resolution by using the first and only platform to combine symbolic debugging, error aggregation, and state analysis. At the time of error, Bactres jumps into
Starting point is 00:40:54 action, capturing detailed dumps of application and environmental state. Bactres then performs automated analysis on process memory and executable code to classify errors and highlight important signals such as heap corruption, malware, and much more. This data is aggregated and archived analysis on process memory and executable code to classify errors and highlight important signals such as heap corruption, malware, and much more. This data is aggregated and archived in a centralized object store, providing your team a single system to investigate errors across your environments. Join industry leaders like Fastly, Message Systems, and AppNexus that use Backtrace to modernize their debugging infrastructure. It's free to try, minutes to set up, fully featured with no commitment necessary. Check them out at backtrace.io slash cppcast.
Starting point is 00:41:31 So a moment ago, you mentioned system error a couple times, and you just gave a talk about that at C++ Now. Do you want to tell us maybe what library developers or library users should know about system error? I know I'm asking you to summarize an hour and a half talk in a few minutes. No, no, that's fine. Actually, it's not hard to do. I can almost do it in a sentence.
Starting point is 00:41:54 We'll get a couple sentences. System error is the standard error code in the C++ specification. We see it a lot in the file system and networking TSs. You'll see more of it. People don't know about it, I think, in part
Starting point is 00:42:10 because everybody hates error handling. It's just annoying. And frankly, it's a tricky problem. It starts messing with your APIs. And error handling as a rule is sort of a very contentious thing because it does reach deep. And the talk kind of goes a little bit sort of a very contentious thing because it does reach deep.
Starting point is 00:42:27 And, you know, the talk kind of goes a little bit why it might be contentious. But in essence, system error is a lightweight little baby thing. It's an int and a reference. So it's 16 bytes, essentially size of int plus size of pointer. And it gives you a type erased platform specific non-lossy propagation of error state and you should use it you're going to get it back from standard apis you should propagate it to whenever you want and maybe you'll do branching logic or conditional processing based on the area you get back but effectively a library developer if he wants to make one, you can define your own. They're called
Starting point is 00:43:06 error categories. You derive from error categories. It's a virtual base. And you do some stuff, and it's not hard. You can do it in 15 minutes. And basically what you're doing is you're saying, here's my set of enums. They correspond with these strings. These are my errors. That's it. Done. And now you can create these
Starting point is 00:43:22 error codes just from the enum. It's implicitly created. And pass it back to somebody else. And they can catch that, get your enum, get the string version, start doing if statements based on what happened, could I not open the file because I don't have permission, whatever it is, and process on it. So everybody, I think, generally has written their own error class for various reasons.
Starting point is 00:43:44 And you don't have to replace that with this. You can. I think generally has written their own error class for various reasons. And you don't have to replace that with this. You can, but, but this is really a great adapter. You can shove anything into an error code. So if you have C errors from C libraries, you can put those in error code.
Starting point is 00:44:00 That's not hard. You know, the libraries are starting to give them to you, but as library author, you can make them, but essentially you're just giving the users the ability to handle enumerated failures for conditional processing that's it they're light they're simple and the talk is long largely because i i try to go into all the very complicated reasons for why system error is so simple and it is simple i think it can evolve more simply.
Starting point is 00:44:26 I think there's improvements we can make to it. But as it stands, it's not a big header. I mean, error code, you got it. You're working with the names. You're done. It's kind of simple. Having seen the talk twice now, I walk away going,
Starting point is 00:44:43 okay, I know I need to do something with this knowledge I now have, but how do I roll this into existing design? Or do I just need to like start a new design from scratch where I'm thinking about error codes? Do you have any like advice? Yes. Yes. Right. You know, putting lots of little, you know, asterisks after it. Every design is going to be different, right? You're going to, you know, error code is not trying to solve so many things that people also need solved. And, you know, I think it's important to separate, you know, what it's going to give you from what it's not. So, for example, it's not going to give you syslog or routing or interprocess anything.
Starting point is 00:45:27 It's just an enum. It's a little enum bundle that's somehow magically associated with the stream. And if you say, okay, well, it's an enum that I can give to my users, well, that's conceptually pretty simple. So as a user, you'll just use it and test against enums. That's hard. You don't have to do any work. As a library author or as a system implementer, there's probably and test against enums. That's hard. You don't have to do any work. As a library author,
Starting point is 00:45:46 as a system implementer, there's probably two levels you're going to go at. One is look, I'm doing this library that does this thing, and here are all the things that can go wrong. You ask for this, I'm going to say no. But I'm going to tell you why. I've broken out a bunch of enums. If you're able to lay out an enum
Starting point is 00:46:01 with these are the cases that may fail, and you might want to tie that to a descriptive string about what that enum means, that implementation, rather than give the user an enum back, you give them an error code back. That's it. So if you're doing functions
Starting point is 00:46:21 where you're returning booleans for true, false, for succeed or not succeed, I'd highly recommend you jump immediately to an enum, because they're more open-ended and extensible. But if you jump to an enum, it's like very little work to jump all the way to error code. So I would just go that far. So what is error code? Well, it's like a glorified enum. But it's a type safe enum that preserves system-specific state. So there's this type erasure mechanism going on in there where, yeah, yeah, yeah, I've got an enum. It's my library's enum, and I publish that. And the user gets an error code, and they say, hey, is this error code looking a lot like that enum coming
Starting point is 00:47:04 from that library? That's all the user needs to know. And that's not hard to do. So really using error code is the act of using enums. However, the implementation of it gives you a lot more power. And once you start going down that road of power, it starts to be, well, I've got this bucket of enums for kind of network problems, and I've got another bucket of enums for kind of my systems, fluidic subsystem kind of stuff, or another bucket of enums for what we call those categories.
Starting point is 00:47:35 I think the proper name is domains. I might have three or four domains. Well, probably most any application, you have like four, five, seven domains. You can have one domain if you want but probably there's several well error code is a better enum in that it gives you this thing called error code that is type erase to where all of your five or six or twelve domains they're all in there i mean you can pass any one of those so you don't have to touch your function function signature where this function might return this type of enum, but that other function will return another enum. Well, what if I have a function that might return
Starting point is 00:48:10 either of those enums? Well, you're screwed, right? I need to pick an enum. Well, no, no. Error code. Error code handles that. It erases that. So you get both of those enums out of that function. So any function that may have problems that ultimately rolls up several domains, well, you don't have to pick one master enum category. And that really is the design of system error. You can't really do a master enum category. We tried, it failed, and that's why we have the design of system error itself. I don't want one master enum. I want a bunch of little domains. Oh, by the way, this function might actively tell you about a couple, three domains might have problems. Now, go ahead. Any gotchas or limitations? There are. Yeah. The biggest gotcha
Starting point is 00:49:00 is instance-specific payload. And if you go into it deeply, the land of structured logging kind of gets into this where I don't want to just say, Enum couldn't open the file. Well, which file? Well, I know that right now. It's this file. So wouldn't it be cool if error code would allow me to stick a little payload in there
Starting point is 00:49:21 for the file name that you tried but failed to open is this file name. Error but failed to open is this file name right error code itself does not have payload now outcome what what niles library did he did put payload in his and and that was interesting now and in the talk i also talk about um well i figured out how to get payload in there you just don't put it in the error code. You put it in the error category. So instance specific error message payload, a lot of people want that. You're going to pay for it, right? It's state that you have to pass around. But if you really want that error code does not have that out of the box, you have to a little bit color out of the lines.
Starting point is 00:50:00 And, you know, the last little thing, which is sort of the second part of you said before, hey, I want to get started. Well, okay, if you have a function that returns a bool, don't do that. Return an enum. If you have a function that returns an enum, but, you know, it could actually return one of a couple of enums because a couple of things might go wrong. A couple of domains might be violated for some reason. Oh, okay, go to error code. You know, for most everybody, stop there.
Starting point is 00:50:21 That's good enough. There is this other deep end of the pool, and I talk about it in the talk, and it's basically the semantic cross-domain mapping. And this is not an error code problem. This is a module API design problem. This is a way of saying, you know, I know at the lowest level that I don't have permissions, the hard drive's full, or the network timed out, or, you know, something happened.
Starting point is 00:50:49 I know at that level what happened. But that's not what the user wants. The user wants something higher level. The user wants to say, I failed to do this thing that you really wanted to do, and maybe I give you some guidelines about, you know, fix this, close that, or, you know, how to get yourself out of trouble. Right. Well, that semantic mapping, that cross domain mapping is I want to somehow map from a very low level of a whole bunch of things might've gone wrong, but I want to map that to this
Starting point is 00:51:15 higher level thing, which is, yeah, your transaction failed. Sorry. But, you know, maybe there's some detail there that I want to preserve, but sometimes you want to throw that detail away. You want a lossy transform. And System Error does have a design mechanism to do that lossy transform. Essentially, the parallel would be if you write code to where you invoke a function, you catch an exception, and you don't re-throw that exception. You throw a different type, a different exception type. That would be an example of a cross-domain mapping. I'm not
Starting point is 00:51:52 throwing what I caught, I'm throwing something else. Okay, well, you've mapped from one domain to another, good for you. Well, system error has a mechanism internally, the way you derive from error category to allow you to do that so i have one of these enums and i'm going to identify that and i will intentionally in a lossy way convert and map over to this other edu and that cross domain mapping that that's a harder uh it's a trickier implementation inside the error category that you write for your domain for your error but it's a trickier implementation inside the error category that you write for your domain, for your error. But it's because you're a library author and you've decided, look, for these cases, I want to map to this. For those cases, I want to map to that. And they might be overlapping.
Starting point is 00:52:35 And that's a design consideration. So it's not an error code problem. It's a design problem. It's a design problem. How would I like to intentionally throw away state, do a lossy discard to provide better actionable context to the user? Because ultimately the highest level, at some point you get high enough where I don't want to hear anything about the subtle nuances of some little database. I just need to know transaction failed. And yeah, yeah, I know that lots of things may have contributed to that. Maybe you can provide me guidance,
Starting point is 00:53:09 but I needed that cross-domain mapping to be provided by your higher level API. So that's really tricky, hard work. It's heavy lift, design lift by the library author. System error is not that complicated. It gives you a mechanism to do it. The hard part is deciding how you would like to do that semantic mapping. How many domains should exist?
Starting point is 00:53:29 At what level? What mappings do you want? Well, system error is just a mechanism. It's not going to help you with any of that. You've given a couple talks now on CPU architecture and how lots of magical things happen uh basically behind the scenes for us and we should be okay with that so i'm just kind of curious like have you like what's your interest and in this stuff oh well um i like to know how things work and and a lot of times you know there's
Starting point is 00:54:03 enough going on in software we We're focused on that. You have enough details there that you can keep yourself busy. And how many minutes in the day do you have left over? But there is this growing concern for hardware at all levels, mobile or heavy lifting, it doesn't matter, that increasingly we are designing software abstractions that drifted a bit, moved away from how the hardware actually works. And we can, without trouble, invent leaky abstractions to where our software system, in theory, is correct. And it is. It just kind of doesn't work. It's either too slow or it has edge cases that are a little surprising. They're correct, but they're surprising.
Starting point is 00:54:50 So I like looking into the low-level details and in part, you know, so there's two things, right? I like understanding how it works because I do think it informs your design. It gives you more options, more degrees of freedom for how to think about the problem but you know there's there's kind of the second thing which is i can't talk about what i really think about a lot of programming practices because my ideas are too out there probably but um in the hardware land it's a little easier because there's not a lot of debate on how the cpu works i, you can have different opinions on what is important and what you think about how it works and maybe even how to leverage it,
Starting point is 00:55:33 but how it works is how it works. So, you know, the talks I've been doing in part because it's interesting, it's useful, it's helpful, and it's constructive. And at some future point, when everybody agrees that we all have a view of how the hardware works, and I think the cash line, if you don't really know what it is, you're going to kind of have to get into it at some point. And at some point, when everybody kind of knows what the cash line is, then we will probably disagree violently on what the hardware does and what the meaning of it is because it kind of gets
Starting point is 00:56:05 into you know the essence of software and the nature of processing and you know the cpu all it's doing is moving bits that's it it what's it it moves bits well no it's doing more no it's not it's doing it's moving bits now there are data objects in there and we might do some instruction decoding and you know we've got a lot of filtering going on because of branching and directions. And, you know, we throw stuff out. And, you know, it's really just moving bits. And, you know, when you start to get into processing, well, we have biological computers now.
Starting point is 00:56:36 And we're doing all kinds of quantum effect processing kind of stuff. And chemical computing now, like, you know, little tubes of stuff that are generating pi, or real mathematical answers. Well, those aren't CPUs. I mean, they're not sitting on little wires where you charge it, there's this electromagnetic wavefront pulse that runs down the wire. I mean, they're doing biology, and they're computing stuff. Well, now you get into the human brain and how's that work and you know i find that stuff fascinating because some of what we do in software i think scales and is a good model provides a good framework to solve problems but some of what
Starting point is 00:57:18 we do introducing incorrect abstractions absolutely take us in the wrong direction and you know that that's kind of the controversial stuff so i can't really have talks about that incorrect abstractions absolutely take us in the wrong direction. And that's kind of the controversial stuff. So I can't really have talks about that because it's just not something. You mentioned the phrase you used, leaky abstractions, and I think I've read that phrase somewhere before, but I just cannot recall the context. Yes. Yeah, so leaky abstractions.
Starting point is 00:57:48 And the idea is, hey hey i have a tape drive and well well i know what a tape drive is it's like it's like a tape and and you can go forward and backwards but basically i mean it's basically a buffered sequential device and oh okay well all right so i'll make an abstraction it's a buffered sequential device and i apply it to this physical artifact that is the tape drive cool we're done well well but you know the tape drive it can seek backwards and it can seek forwards too so i could if i wanted i could present it with a non-buffered random access api i could abstract a non-buffered random access interface to the tape drive. It'll be slow, but it'll work. It'll work absolutely fine. Okay, well, at some point, if I do that, the impotence mismatch between my design decision of non-buffered random access to
Starting point is 00:58:38 the tape, my latencies are awful, right? It works, but at some point there is enough leakage of real world, the tape under the hood is being thrashed back and forth and I can't get anything done within a year on my computer that my abstraction just kind of fails. So reality under the hood leaked up through my abstraction and my abstraction fails. And, you know, I'd say, you know, one of the good examples today would be, hey, I want to do this low latency distributed system. Well, that's cool. You know, there's this internet thing. I hear it's going to be big soon. And so if I want to do low latency distributed stuff, well, that means I probably want to cash and I'm going to probably need local storage because I need low latency. I want to go fast. No, no, no, no. A hard drive is a tape that runs fast. And mechanical sympathy and some other people have talked about this, but essentially a hard
Starting point is 00:59:40 drive is a fast tape. It is a tape. If you want to go fast, you go to the network. You would never, ever, ever in a low latency asynchronous system, go to the drive. I mean, it's just too slow. You go to the network. Oh, what do you want? Well, I want random access, you know, non-buffered stuff. Oh, wow. Well, well, the network abstraction is actually a way better abstraction for random access non-buffered. You know, your hard drive really is a sequential access buffered thing. It's a tape. And so, yeah, so, you know, as you start looking at how the world actually works and then the abstractions you want to put on top of them,
Starting point is 01:00:19 if your abstractions are just insane, I mean, they're correct, right? You know, you can implement a random access tape drive. It's just going to cost you. And it's cost that serves no purpose. So, you know, it's kind of like, you know, we're programmers and, you know, I bought this goldfish and I brought it home. It's a lovely goldfish and I love my goldfish. And, you know, the poor thing is starving to death because I don't know how to feed that guy. And, you know, it's a beautiful goldfish and it hasn't died yet. So, you know, we can call that success, but, you know, we're all bringing home these CPUs, you know, these goldfishes and we're starving them to death and they're in the bowl and they're choking saying, give me bits. And our designs just won't do it. And it's like,
Starting point is 01:01:02 we're the meanest people ever. So yeah, I think when you learn a little bit more about what your goldfish needs and its dietary requirements, feeding your goldfish won't be such a problem. But you know, goldfish are people too. And there are a lot of goldfish out there that are suffering daily. And you know, I'm on a mission to make sure no goldfishes die. Well, they're going to die, but sorry. Needless to say, you think it's important for C++ programmers to have some understanding of their hardware. Yes, largely because we have control of that, right? You know, C++ and then C, we directly address the instruction set architecture, which is the interface of the hardware itself.
Starting point is 01:01:40 So the chip vendors, they give us the ISO, the instruction set architecture, and they say, this is how you address my hardware. And they give us all the guidelines and everything they can to let it be productive. And, well, our language has that C, C++. But, you know, Python or some of these higher-level languages, they don't have a prayer of that. I mean, they might be able to do some really good implementations in JVMs or JVM or whatever to make it better. But they fundamentally cannot, cannot, cannot implement abstractions that model how the hardware actually needs to be fed. We can. And as a result, like anything else, you don't have to pick up all the money laying on the table.
Starting point is 01:02:24 You don't have to. But if it's easy enough, it might be good to do that. And well, our language gives us the tools. And, you know, frankly, that's really what C++ 11 and then 14 and then 17. It's really what they're doing. If you go in there and you start looking at all that stuff, you know, our value references and languages and whatever, There's a bunch of stuff. It's good stuff. It's stuff I want. It's stuff I really want to use.
Starting point is 01:02:48 But almost all of that stuff is ways for the program to articulate to the compiler, this is what I'm trying to do. And giving the compiler the discretion and the power to generate efficient assembler to let the hardware do its job. So frankly, we in the modern C++ era, we are talking very intimately to the compiler, whispering sweet nothings, providing hints. The compiler will have to figure out how to map it to some specific target architecture and make trade-offs, and they're very good at doing that, and they're getting better. But largely, our act of software professional engineering is the act of, frankly, talking to the compiler. It's weird, because in
Starting point is 01:03:40 the olden days, it was talking to other programmers for portable assembly. Well, not anymore. I mean, with the new language features, that's not it. It's hints for the compiler. That's it. Charlie, it's been great having you on the show today. Where can people find you online? Oh, my email address is on all the, if you go to the BoostCon or the CppCon talks, I have my email address on the front of the talks, but I don't really have Twitter or anything because
Starting point is 01:04:05 I haven't figured out this internet thing yet. It's just a fad anyway. Yeah, it'll fade out. Okay, well it's been great having you on today. Hey, thanks a lot. It's been great. Thanks for joining us, yeah. Take care. Thanks so much for listening in as we chat about
Starting point is 01:04:24 C++. I'd love to hear what you think of the podcast. Please let me know if we 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
Starting point is 01:04:50 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.