CppCast - Regular Void

Episode Date: December 21, 2016

Rob and Jason are joined by Matt Calabrese to talk about his Regular Void Proposal, template<auto>, the state of Concepts and more. Matt Calabrese is a software engineer working primaril...y in C++. He started his programming career in the game industry and is now working on libraries at Google. Matt has been active in the Boost community for over a decade, is currently a member of the Boost Steering Committee, and is a member of the Program Committee for C++Now. Starting in the fall of 2015, he has been attending C++ Standards Committee meetings, authoring several proposals targeting the standard after C++17, notably including a proposal to turn the void type into an instantiable type and a proposal for the standard library to introduce a generic algorithm for invoking standard Callables with argument types and argument amounts that may be partially calculated at compile-time or at runtime. He is also the author of the controversial paper "Why I want Concepts, but why they should come later rather than sooner", which may have contributed to the decision to not include the concepts language feature in C++17. News 2016 Software Developer Podcast Awards My take at times A C++ program to get CPU usage from command line in Linux Pointer comparison an invalid optimization in GCC Matt Calabrese @cppsage Links Boost C++Now P0146: Regular Void (Revision 1) P0376: A Single Generalization of std::invoke, std::apply, and std::visit P0240: Why I want Concepts, but why they should come later rather than sooner Sponsor Backtrace

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 83 of CppCast with guest Matt Calabrese recorded December 21st, 2016. In this episode, we discuss the 2016 Software Developer Podcast Awards. Then we talk to Matt Calabrese, member of the C++ Standards Committee. Matt talks to us about his regular void proposal and more. Welcome to episode 83 of CppCast, the only podcast for C++ developers by C++ developers.
Starting point is 00:01:18 I'm your host, Rob Irving, joined by my co-host, Jason Turner. Jason, how are you doing today? Pretty good, Rob. How about you? Doing good. Looking forward to the holiday season coming up. This will be our last episode for the year. Yeah. Really? We'll be back in January, right?
Starting point is 00:01:34 Yes. Yeah. We're taking off next week, but we will be back. And we actually still need to line up some guests, but I'm sure that won't be too difficult, right? No, it shouldn't be a problem. and yeah i'm curious so this is a sunday to sunday holiday week which is a little unusual yeah are you taking off the whole week uh i am going to be taking off all of next week gonna be traveling up to lovely new jersey to see my family yeah i'm just wondering if lovely was meant sarcastically a little yeah okay um well it's our episode i'd like to read a piece of feedback um this week uh hopefully i can
Starting point is 00:02:18 pronounce this right gisline writes in saying hello uh first good job on the show i listened to it in my commutes to and from work and i look forward to it every week i want to make a suggestion for a subject it's unfortunately pretty broad and probably not that useful but anyway here it goes i think it would be nice to have something about c++ in the medical field i personally work in radiation therapy as a physicist and know that computers are now heavily used in the medical field but i don't know what place c++ has in that field would have been nice to find medical field, but I don't know what place C++ has in that field, would have been nice to find out.
Starting point is 00:02:47 As a more precise suggestion, I know of the DCMTK library. Maybe someone from that library would have the time to be a guest on the show and discuss where this library is headed and how much it's used and such. Anyway, congrats on the show and nice holidays to you both. So thank you, Ghislaine. Yeah, I'm not too sure about the use of C++ in the medical field, but I would assume that a lot of the, you know, machinery and diagnostic equipment might be powered by C++, right? Yeah, I actually know a few people in the medical devices industry
Starting point is 00:03:20 who use C++. And there's two or three companies just here in Colorado that are medical devices. Well, maybe you might know someone who would be a good guest for that topic. I know some people. I don't know how much they would be able to talk about what they do. Right.
Starting point is 00:03:36 But I could look into it. Yeah. Okay. Yeah, it's something we'll look into. 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 cppcast.com. And don't forget to leave us a review
Starting point is 00:03:49 on iTunes. Joining us today is Matt Calabrese. Matt is a software engineer working primarily in C++. He started his programming career in the game industry and is now working on libraries at Google. Matt has been active in the Boost community for over a decade, is currently a member of the Boost steering committee, and is a member of the program committee for C++ Now. Starting in the fall of 2015, he's been attending C++ Standards Committee meetings, authoring several proposals targeting the standard after C++ 17, notably including a proposal to turn the void type into an instantiable type and a proposal for the standard library to introduce a generic algorithm for invoking standard callables with argument types and argument amounts that may be partially calculated
Starting point is 00:04:29 at compile time or at runtime. He's also the author of the controversial paper, Why I Want Concepts, But Why They Should Come Later Rather Than Sooner, which may have contributed to the decision to not include the concepts language feature in C++17. Matt, welcome to the show. Hi, thanks. Thanks for having me. So you've made an interesting switch in your career here. It seems like there's so many programmers that are like, I want to program in games. And you did games, and you're like, enough of that. Now I'm going to work on libraries. So I'm curious how that went.
Starting point is 00:04:59 Well, I've always kind of worked in libraries. But the game industry thing is just, like you said, a lot of people just, oh, they would love to work in games, they'd love to work in games, but when you actually get into the industry, you realize that it's not quite as fun, or at least I didn't find it quite as fun as all the library development that I'd done in the past. So even when I got in the game industry,
Starting point is 00:05:20 I was already participating in the Boost community, I'd written a bunch of generic libraries, and that was more kind of my thing, and that's not quite as embraced in the game industry i was already participating in the boost community and written a bunch of generic libraries and that was more kind of my thing and that's not quite as embraced in the in the game industry so so you said it's not as much fun as you might think did you was there like the crunch culture or whatever the people you're always it's always crunch time it feels like you're always accumulating technical debt and that could be just the experience it feels like you're always accumulating technical debt.
Starting point is 00:05:47 That could be just the experience that I had. I was at a THQ studio, and I joined late in the development process of a game, and maybe that was just a symptom of that. Another thing I've heard about, at least with the AAA game studios, is that you're just working on one piece and always improving the performance of it, improving capabilities of it, but you're not really working on a game as much as just this one tiny piece of the game, right?
Starting point is 00:06:11 Yeah, that's true. And like what I was doing when I was at the THQ studio is I was doing a lot of tools development and making like the world editor, things like that. So yeah, you really only see a small part. It's like, yeah, technically I was working on a game, but it doesn't feel like it when you're doing it quite as much. I imagine in smaller studios where you're actually maybe like three or four people or something, but here we had, I forget how many programmers. It was definitely multiple, maybe like 40, 50 or more.
Starting point is 00:06:39 Wow. I've never worked on a team that big, even that big, yeah. Okay, Matt. Well, we got a couple articles to discuss and feel free to jump in on any of these and then we'll start talking to you about the void proposal and some other work you've been doing. Okay. Okay. So this first one is the 2016 software developer podcast awards. And this award thing is kind of a new idea that um john sonmez put out he is a fairly popular programming blogger he's got simpleprogrammer.com and for a couple years now actually he's
Starting point is 00:07:16 maintained this blog post as a list of different software development podcasts and i'm proud to say that cppcastast is listed there. It is listed as the one and only C++ podcast, which is great. And he decided that he would kind of make an award out of this list because he's got multiple Java podcasts, multiple Microsoft podcasts, multiple JavaScript podcasts. So he's letting people vote on these different categories. And I think there's going to be like two rounds of voting
Starting point is 00:07:48 where all the winners from the first round from these different subcategories will then compete as just the best podcast. So please take a look at this link. You do not have to vote for every category, which would be kind of silly because I have no idea what these different JavaScript podcasts are, so I wouldn't know which one to vote for is the best. But you can vote for whichever category you're interested in.
Starting point is 00:08:14 So you could vote for us, and if there's other software-related podcasts, you might find them on the list and vote for them as well. I will say we are definitely hoping to win the C++ podcast category. We got some pretty stiff competition, right, Jason? Yes. Yeah, we are the only one listed under best C++ podcast, which I was a little surprised by because right under us is best miscellaneous language podcast. And in there, there just seem to be other podcasts that maybe don't have enough entries for their own category. Right. So why are we not in them?
Starting point is 00:08:52 Elixir. I think Elixir is a programming language, right? I don't know. I'm not exactly sure what that is. But I'm not sure why he decided to put us into our own categories instead of doing the best miscellaneous language, but I'll take it. Yeah, but some of these things are shocking, like 20-some-odd in JavaScript category. Yeah, there are a lot of JavaScript podcasts. Five PHP podcasts.
Starting point is 00:09:17 Five PHP. I'm looking at seven.NET Microsoft-related podcasts, four for Java. Yeah, there's a lot of programming podcasts out there you know i'm thinking maybe we're not in the general or whatever um miscellaneous language because all those if you look at the language itself they're small rarely used languages that could be maybe it's more commentary on the language not on the podcast yeah that would make sense yeah because definitely c++ deserves to have its own category like like java and dotnet and those other ones too yeah yeah okay uh this next one is kind of a follow-up to one of the
Starting point is 00:09:59 articles we talked about last week with the c++ version of Ruby's integer times. And John Kolb decided to take his own stab at implementing this type of functionality. Only he didn't want to do the Ruby style syntax of 42 dot times or underscore times. And in the case of that blog post, you wanted to just make a pure function that would take a number and take a callable function pointer or lambda and be able to execute it multiple times based on the number. What are your thoughts about this, Jason? I think it's a good article,
Starting point is 00:10:38 and I think there's probably something for most C++ programmers to learn from reading this. Some SphinA tricks to decide which version of times to call and some other tricks on making it more general further down. Yeah, and he
Starting point is 00:10:56 made a much more complex version of it because his allows you to say, I want to do from 10 to 20 incrementing in units of five instead of just one so you can get a lot more complex with his version of it yeah yeah i thought i just saw a bug but i think i was wrong uh next one uh a c++ program to get cpu usage from the command line in linux is this something you think you would make use of, Jason?
Starting point is 00:11:27 It is the kind of thing I have done before. The official way to get these things is from the proc file system, as he's showing here, or he or she, whoever wrote the article. It's kind of mostly about parsing files, the proc stat file. But it's still an interesting read, yeah. And this next one is about pointer comparison and how this author thinks GCC is making an invalid optimization
Starting point is 00:12:01 and that you can basically compare two pointers and even if they should be equal is his argument gcc will say they are not and i think he's got a pretty good argument i mean it makes sense to me so matt did you look at this one unfortunately i did not look at this i i skimmed it a while ago and i skimmed it just before uh we started recording and uh yeah i i'm i'm not enough of a language lawyer to really uh be able to analyze it enough to say one way or the other i did shoot an email to uh somebody in the standards committee about it though to see what their response would be okay so it's quoting the c standard as opposed to the c++, so it could be different. It is.
Starting point is 00:12:46 Right. So the point that he makes, let's see if I can find it real quick. Both pointers, two pointers can be considered the same, and there's an explicit wording that says, one is a pointer to one past the end of one array object, and the other is a pointer to the start of a different array object that happens to immediately follow the first array object in the address space
Starting point is 00:13:09 so he puts two arrays adjacent to each other compares the two pointers one past the end of the first one the one at the beginning of the second one and it returns false that when you turn on optimization but someone down in a comment points out, and I don't, obviously, I'm not a language layer enough to understand this either, but they point out that his example is using the stack. There are arrays in main on the stack. But if you were to put those two arrays inside a struct
Starting point is 00:13:40 where the memory model guarantees that they are actually adjacent to each other, then GCC does not perform the optimization that he thinks is invalid. So there you go. Interesting. Well, I'll definitely need, I guess, a language lawyer's opinion on this. In most contexts, I would consider myself a language lawyer, but not here. Okay. Well, Matt, let's start talking about the regular void proposal.
Starting point is 00:14:10 What exactly is the point of this proposal? Okay. So the point of regular void is, well, it has two points. The first point, which is like the main motivation is that when you're writing generic code, very often you want whatever your code is templated on to work equally well with void as it would with other types. A good example where this comes up in the standard library, it's a symptom of the fact that void is not regular, is we have like these specializations for std promise and std future for the void type, where if you want to, for instance, execute a function asynchronously
Starting point is 00:14:45 and get back a future to the result type, you want to be able to do that with void just as easily as you can with other types. Like if your function had returned an int, it would work perfectly fine. Why doesn't it work perfectly fine for void? And the answer is we force it to work in the standard library by just creating a specialization with a slightly different interface, just so that way you get a similar type of functionality. So the goal of this proposal is to just make it so that void is like all the other types that we have in the language, all the other regular types that we have in the language, so that you don't need these types of specializations for std promise, std future. The proposed std expected also has a special case for void. The proposed stood variant,
Starting point is 00:15:26 which is now in CBLSW 17, for a while had special casing for void, but we actually just cut it out at the last standards meeting. So it's definitely a problem that a lot of people encounter, both inside and outside of the standards committee. And so this just seems like the best way to make it work. And so I use the word regular a bunch of times, and I realized I never actually defined it. So when I say I want void to be a regular type, the term regular comes from the generic programming community. And it basically means that your type is well-behaved with value semantics.
Starting point is 00:16:00 And by that, I mean it can be copied and moved around. A copy and an assignment both result in a separate object that has an equivalent value to the original object and they have this property called substitutability where if you have a function and you call it with one value, you're able to call it with a copy of the same value, and you'll get back the same result. So these are all just kind of properties that you expect out of things like ints, floats,
Starting point is 00:16:31 and any well behaved type that you would make on your own any well behaved user defined type. And so we just want to make void exactly the same. And so in doing that, we basically just make void a monostate type. So it can only ever have one value if you wanted to analyze it in that sense, we basically just make void a monostate type. So it can only ever have one value if you wanted to analyze it in that sense. You can make an instance of it, you can copy it around, you can return it from functions, you can even compare them, they're always compare equal. And so that's just basically the general idea. And so in practice,
Starting point is 00:17:01 most people won't be using this, the people who take advantage of it are people who are just writing templates. It just means that they don't have to make a special case for it, or equivalently, if you're using a template and you don't want to special case it. So to be clear, you're saying you would be able to create an object that is type of void, or you could have like void space V semicolon, that would be valid code? Yep, you would, you would be able to do it. Yeah, I mean, so this is I'm saying you would be able to do that. That's if my proposal goes through.
Starting point is 00:17:26 I'm currently on the second revision of it. The first time I brought it to the standards committee, it had kind of mixed results. I came back, and it had very positive results. And the head of EWG and myself agreed that before we went further, I wanted to come back with an actual implementation in Clang and test it out with existing code bases, make sure nothing breaks. But the whole point of the proposal is I try not to break anything at all. And I've had it looked over by people in core, and they agree that it should be a perfectly valid change to make, and they don't foresee any problems.
Starting point is 00:18:01 It's not going to be an ABI break or anything. So I'm pretty confident that eventually I will be able to convince the remaining people who hold out against the idea that it is in fact a good idea and a safe change to make. So I'm hoping that by C++20, I'll be able to say that I was able to turn void into a regular type, which would be pretty cool. So this concept came up on the CPP Slack when I was on there recently. And before I forget, I promised them that I would ask, what is the size of a void object? Ah, so this is actually a really good question. So in an ideal world, if we were designing C++ from scratch,
Starting point is 00:18:42 which unfortunately we're not, it would be great if we could have size++ from scratch, which unfortunately we're not, it would be great if we could have size of void be equal to zero. And one of the reasons why you want this is, let's say you're writing generic code, and maybe you have a tuple of all of the results of function calls, and the functions that you're calling happen to be dependent types. So in other words, they're dependent on a template argument. In the case that those happen to return void or something like that, you don't want them to actually occupy space in this tuple, you want them to logically occupy an element of that tuple, but you don't want them to contribute to the overall amount of space that that object takes up.
Starting point is 00:19:19 And so ideally, that would be what we'd want. But unfortunately, because of existing language rules, it's really difficult for me to actually make void equal to zero, size of void equal to zero. Some of the problems that you encounter are if size of void is zero and you want to be able to take advantage of it in a way that makes it so that it doesn't contribute to the overall size of an object, then that means that you eventually end up with cases where you'd have two void objects that occupy the same address in memory. And so this is one particular kind of problem.
Starting point is 00:19:57 Like, normally when you have objects in C++, if you have two distinct objects of the same type, they can't share an address. So this is kind of like what I consider a minor problem with having size of void be zero, but it would be a difference from other types that we have in the language. And that can potentially manifest itself in generic code if you're relying on this property of all object types occupying different addresses. But the more troubling one that I find is if you have size of void equal to zero and you make an array of them, if you were to use something like a range-based for loop where you give it like a begin and end iterator of your array, if you use that with an array of void, no matter how many elements there are it would execute um no times at all because the address of the end location and the address of the zeroth location would always be equal so you'd never be able to see any iterations that
Starting point is 00:20:58 take place and you might not think this is a big deal but because you know obviously what can you possibly do with void but you have to keep in mind mind that the body of the loop can be doing side effects. And you can't just assume that because your elements are void, that your loop doesn't have to run the amount of times that it should. So this is kind of like a subtle thing. And it's really, it's like a symptom of the fact that in C++ and in C, we kind of, well, mostly in C++, we think of pointers into an array as iterators. And in fact, we not only think of them as that, I mean, that's how we effectively define them. And our whole iterator concepts are kind of based around this whole notion of, or they're modeled after how pointer arithmetic works. But really what we should have done is had a different kind of iterator type for arrays from pointers.
Starting point is 00:21:49 Pointers shouldn't be able to have pointer arithmetic in general, and it's just because already it's only really defined if you're iterating over elements of an array anyway. What we really should have done is we should have had a separate iterator type for marching over the elements of an array, and in which case if we actually had that and it was different from our pointer type, you'd be able to have a size of 0 type,
Starting point is 00:22:09 put it into an array, and its associated iterator type could just be equivalent to an integer that counts when you increment it. And then you wouldn't have this kind of subtle difference between behavior if you have an array of some non-zero size and an array of zero size elements.
Starting point is 00:22:27 So I don't know. Those are basically the issues. So as I said, size is not zero. Size, as I describe it in the proposal, is that it's some non-zero size that's implementation dependent, which is a common thing that we do for a lot of different types. In practice, I expect that to mean that the size is going to be one
Starting point is 00:22:48 and there's a really good reason to believe that size will be one in practice even if you didn't already consider it like why would you want something larger than that but GCC already allows you to as an extension like increment void pointers in which case it's going by one and so that would be a change in behavior
Starting point is 00:23:04 of their extension if all of a sudden they made size of void something different. But that's that. It kind of sounds like it's an overlap with the size of an empty struct being one also. Yeah, exactly. I think if we were to ever solve the problem in C++ where we can't have size zero types,
Starting point is 00:23:24 it wouldn't be like void would be the only size 0 type. There would be some way to opt in for your type being actually size 0. I think that's the only way we'd be able to do it. It would have to be like an opt-in mechanism, and it would solve it for empty structs in addition to solving it for void. It's out of scope of this proposal.
Starting point is 00:23:40 It's something that I wish that we could have in the language, but I think it's not really feasible, just based on legacy concerns. And it would be a bigger change than what this proposal is. So I'm curious, and maybe this is going too far off into the weeds, but if you were to have a struct that had like five void variables in it, do you imagine the compiler doing any optimizations like it does with empty base optimizations, like compacting those into one thing? No, I don't expect it to happen.
Starting point is 00:24:12 I expect it to be treated by the compilers basically exactly the same way that it would treat an empty struct, which is they can't compress them there. So yeah, you'd have to, if you wanted to be optimal, you'd have to do what people do today already, which is either exploit the empty base optimization. You wouldn't be able to do that specifically for void because you can't inherit from a fundamental type, but you'd have to do similar kinds of tricks if you wanted it to actually occupy zero space
Starting point is 00:24:36 in your struct that contains your void objects. But that's not a new problem. That's a problem that library developers already have to deal with, and it's unfortunate. And I hope that someday we'll be able to get by that, but it's definitely out of scope of this proposal. So you said with the first iteration of the proposal, you did get some pushback from the standards committee. Could you tell us a little bit about what the pushback was? Yeah. what the pushback was? Yeah, so I think part of the initial pushback was I didn't make it quite as clear in the proposal that I as I could have that I wasn't breaking existing code. And so
Starting point is 00:25:14 I think a couple of the people who I, I spoke to in the months following, because I wanted to really understand what the what the negative response was before I made a revision. A lot of it was just confusion over what exactly the details were of the proposal. And it was sort of my fault when I presented. I was kind of expecting – it was my first standards committee meeting. I was expecting everybody to have, like, read every paper, which is completely impossible. And everybody would have understood, like, every paper really well, because I had full wording in the standard for all the changes that would need to be made in the standard.
Starting point is 00:26:09 And if you were to read all of the changes, it would be very clear that basically all that I do is I eliminate parts of the standard that say things like except for void or including void. I'm basically just removing a whole bunch of special cases from the standard. And I'm not actually introducing like, uh, any new incompatibilities with things or making it. So you have to special case, but one of the claims was that, that it would require people to special case void in their, in their code more, which is just, it was just an incorrect thing. Uh, but there were other, there were other things that people were pushing back on that, um, are harder to write off. And they're things that I'm sympathetic to, even though I disagree with. One of them is that currently today, if you have a void pointer, and you write delete of that void pointer, your compiler can can tell you, hey, no, you can't delete, you know, void. But this today would obviously allow you to be able to delete a void pointer pointer because it's possible
Starting point is 00:26:45 that it's actually pointing to a void object in which case that's a perfectly valid thing so if if if you really think that the trade-off is not good where you get void being a regular type because you think that you lose the ability to catch people accidentally deleting void pointer i can't really argue with that i disagree disagree with it, but people weigh things differently. I don't know. Does that introduce an ambiguity of some sort between a void pointer being like a generic pointer and a void pointer being a pointer to a void thing?
Starting point is 00:27:22 It's not really an ambiguity. I mean, you already have the ability in the language to have pointers of different types, alias, other things. Another example that's commonly done is like char. Lots of times people will have char pointers to existing objects that are of a different type. So if you were to, for instance, dereference the void pointer, and it didn't actually point to a void object, then that would be undefined behavior,
Starting point is 00:27:51 just as today, if you have a mismatched type, and you're pointing to an object of a different type, and you dereference it, it's undefined behavior. Well, I think the act of dereferencing it technically is an undefined behavior if you actually access the object. But either way, it's not really introducing something new in that respect. Okay. Would regular void mean there's a change in sometimes you might have func void versus just having func with empty parameters? Would that be different now? So you mean like if a user wrote in their function declaration like void foo, open parentheses void?
Starting point is 00:28:30 Yeah, right. So this is an interesting case. So like I said, a part of this proposal, I really do not want to break any existing code. And in an ideal world, you would actually want like void foo, open parentheses void to mean something taking a void parameter.
Starting point is 00:28:47 And that obviously conflicts with what its current meaning today is, which is a nullary function. So this is like one of the only special cases that I'm just completely unable to remove. So that specific type will not change in meaning. So if you write that out, it will not change in meaning. However, if you actually want a function that takes a single void parameter, you can just give that void parameter a name.
Starting point is 00:29:11 So in other words, instead of writing void foo, open parentheses, void a, void, close parentheses, you can write like void a to give it a parameter name. Then all of a sudden,
Starting point is 00:29:20 it's a unary function. Similarly, this is only true if you're at global scope or if you're not inside a template. If you're inside a template and the void comes from a dependent type, for instance, if you're thinking about std promise, std promise has a member function called set value. And it takes something dependent on the type T. So like set value and it takes something dependent on the type t so like set value you set the value that the future is going to see and in this case if you had a future of a promise of void the signature of this function would be um set value and it would take like a t ref or something t reference or maybe a t ref ref uh In this case, it actually would correspond to
Starting point is 00:30:07 a unary function as opposed to a nullary function because the type is dependent. And also because in that case, it's a reference. But if in the cases where your type is dependent, you don't need to do anything special, you don't even have to give it a parameter name. But that's that. That's interesting. You know, personally, I've always been it just makes me sad when I see functions that are explicitly nullary. So I would have You know, personally, I've always been, it just makes me sad when I see functions that are explicitly nullary. So I would have been okay if you would just change that part of the standard. Well, we can't really do that. I mean, you can't change, you can't change, you can't change, you know, all the code that's been written over all these years,
Starting point is 00:30:39 and you want to be somewhat compatible with C. And when I actually originally wrote the proposal, I was talking a bunch with Richard Smith, and he recommended maybe I should even try deprecating the meaning of void, foo, open parentheses, void, closed parentheses, because he also considered it, and other people in the committee consider it sort of a mistake that we have the meaning
Starting point is 00:31:05 that it currently uh that it currently has yeah and so did uh when i initially presented it i had it with like a deprecation there and there was pushback because people didn't want to actually deprecate that meaning for the sole reason being that if we deprecated it there's basically no way we'd ever be able to change the meaning anyway, because we're probably not going to be able to get C to change the fact that that means a nullary function. So in the revision, I removed that deprecation. And that actually won more people over to the side of the proposal. So. Okay. Yeah. So you have other proposals out that take advantage of template auto parameters that was added in C++17. This is something I haven't yet played with. So I'm kind of curious, what is an auto parameter in a template?
Starting point is 00:31:57 And how does that differ from a template type name or class parameter. So template auto. So this is a proposal that that was done by James Tuton and Mike Spertus. And so you mentioned template type name and template class, I'm sure you're also familiar that you can have non type template parameter kinds, such as like template int. Yes. A common one is stood array for listeners listeners. Std array takes a class for the first parameter, and then its second parameter is a size T of the size of the array. So that's just a compile time constant integer that you can pass. So what template auto is, is it corresponds to a non-type template parameter kind that is deduced.
Starting point is 00:32:50 And specifically, it has to be a non-template. It won't bind to template template parameters, but it will bind to any type of other non-type template parameter kind. So for instance, in the standard library, we have something called std integral constant, which takes some type as the first template parameter, and then an instance of that type as the second one. So you might write like std integral constant, open angle bracket, int comma five. And this represents in the type system, a constant of type int that has the value
Starting point is 00:33:18 five. But one thing that you have to do there is you have to explicitly type out int, because you have to use it when declaring the second template parameter. What template auto does is it allows you to instead of having something like std integral constant that takes two parameters, you can make a std integral constant that takes exactly one auto parameter. And if you pass in something like the value five, then it will automatically deduce the value type of that to be int in that case. And another example is if you write open angle bracket and you just wrote like a single quote, a single quote, end angle bracket,
Starting point is 00:33:52 it can deduce it as a char. So it corresponds to any value type that's a non-type template parameter kind and deduces that for you. So it mostly just eliminates some redundancy that people have to do when they're when they're doing any type of metaprogramming or things like that. So that kind of feels like it overlaps with C++17's class template type deduction. Um, not, not really, because what this does is this actually affects the template parameter, like not the template argument list,
Starting point is 00:34:26 but like the actual template parameter list of the template itself. So it can change from things that currently today you need like two template parameters for now become like a single template parameter. So it actually changes the type itself, not just how things are deduced. So it's a little bit different from that.
Starting point is 00:34:47 Okay. So you have then made some proposals for C++20 that take advantage of this new feature in C++17. Is that correct? Yeah. Yeah. So I think three of my proposals touch on it a little bit, but the two ones that feature it as the main thing is that they use this feature. One of them is we were talking about stood integral constant.
Starting point is 00:35:13 I propose having just stood constant, which I can just verbally explain the exact definition because it's so simple. It's template template open angle bracket auto close angle bracket um using constant equals stood integral constant and then decal type of the parameter comma the parameter value so it basically is just an alias of stood integral constant that um that automatically deduces the value type for you uh okay. So that's, that's just a very simple one liner proposal. I only, I presented it once to a small subgroup, a subgroup of LEWG, just to get some feedback. And I plan to come back with
Starting point is 00:35:56 it and actually formally propose it. And then the more interesting proposal that I have that uses it is what I call monostate function. And what monostate function is, is it's a type or it's a template that takes a single, a single auto template argument. And what you normally try to pass to it is the is a function pointer type. For me, let me think if I could explain this a little bit a little bit better it's hard to explain it verbally without code let's say you have let's say you have a stood set and you want to override the comparator for your stood set and specifically the type of the the type of your comparator that you want to pass uh corresponds to something that you want to pass corresponds to something that you already have as a function. So not as like a function object, but just a function. And you want to just specify, hey, I want to use this
Starting point is 00:36:52 function here as the comparator. What you'd have to do today, or one of the ways you can do this today is you can specify a function pointer type as your comparator kind. And then in the constructor of your set, you can initialize your comparator by passing in an instance of the of the pointer that corresponds to the function that you want to call. But this is kind of horrible, because it's it, it requires the user to be redundant, they have to specify a function pointer type manually. If they forget to initialize the comparator when they create an instance of their set, then they have undefined behavior if they go and try to actually insert things into their set. Another example of this is, let's say you want to have a deleter for your
Starting point is 00:37:36 unique pointer, and you have some kind of deletion function that already exists. And again, it's just like a function pointer. You want to be able to somehow specify that specific function as a deleter and currently today you'd have to put like a function pointer type as the deleter and then pass into the leader manually what monostate function which is the thing i'm proposing uh does is it just takes it's a temple that takes a single a single auto parameter and you give it something like a function pointer type, and it turns that function pointer into a function object that occupies no space, but that when you default construct it, it's fully formed, and it has an overloaded function call operator that will just call your original function that you passed it. So it allows you to do things like create deleters
Starting point is 00:38:23 for unique pointers, or create comparators for things like sets, and have them work with a function pointer. And you just do it right at the place where you create, or where you name the type of your set, or you name the type of unique pointer without having to add any other type of initialization through the unique pointer or sets constructor. I don't know how clear that was, but... I think it makes sense. It's like your constant proposal, and in this case, the constant is the function pointer, and you add a call operator. Right, exactly. So where a std integral constant takes some compile time constant value and exposes a colon colon value, what this does is it takes a compile time constant function pointer, and it exposes a function call operator. And in either case, the std integral
Starting point is 00:39:10 constant, you know, is an empty type, and the monostate function is an empty type. But they give you a way to kind of pass the information about what the value is that you're representing in this stateless type. So you don't need to initialize it, you don't need to do anything else at runtime. It's interesting, I was for a parser that I'm working on, I did something similarly, but obviously not using the C++17 features for, um, string constants that gave you some, you know, begin and kind of functionality on a string constant. Yeah, that's cool. It seems to be like a recurring kind of theme where we have these runtime values and you want to be able to pass them around
Starting point is 00:39:52 and have their value be a part of the type system. So something a little bit even more compile time constant than constexpr, something that's actually tied to the type of the variable that you're passing around. I think auto makes it easier to do some of these things. So it'll be interesting to see how this feature plays out in future standards, what kinds of uses people come up with.
Starting point is 00:40:14 I have to play with that. 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 life cycle. 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, Backtrace jumps into action, capturing detailed dumps of application and environmental
Starting point is 00:40:43 state. Backtrace then performs automated analysis on process memory and executable code to classify errors and highlight important signals such as heap corruption, malware, and much more. This data is aggregated and archived in a centralized object store, providing your team a single system to investigate errors across your environments. Join industry leaders like Fastly, Message Systems, and AppNexus that use Backtrace to modernize their debugging infrastructure. It's free to try, minutes to set up, fully featured with
Starting point is 00:41:11 no commitment necessary. Check them out at backtrace.io slash cppcast. Do you want to talk about concepts for a bit? You mentioned in your bio that you think you might be responsible for concepts not making it into C++17. I don't think, I don't think, no, I actually, I don't think I'm responsible.
Starting point is 00:41:29 I, I, I, I wouldn't be surprised if I contributed to some of that. And that's not something that like, I'm, it's not something I would say I'm proud of. And it's not something that I would say that I'm, that I'm not proud of. I basically just expressed my opinion that I did not think that, that they were ready. Uh, but a lot of people apparently shared that opinion, uh, as, as is obviously the case because didn't actually end up getting into a C plus
Starting point is 00:41:53 17. Um, so what is your argument? Why do you think it was not ready yet? So my, the reason why I say that I don't think I influenced much, uh, much of the standard committees,
Starting point is 00:42:02 uh, decision there is because my concerns are actually very different from what uh what a lot of other people had for concerns okay uh so what a lot of other people's can i'll talk about what other people had uh issues with for concepts but before my own but uh some of the some of the problems with concepts were that we didn't in conjunction with the actual feature have a standard library that was making use of concepts. So we didn't really have a proof of concept yet. We have ranges.
Starting point is 00:42:33 Ranges is probably the best use case for concepts that they've been using it for quite a while, and they don't seem to have very many problems with it. But we don't have anything actually in the standard. so that was something that bothered some people a little bit bothers me a little bit but um that's not my my biggest issue another thing was the the the language feature introduces some new ambiguities that were unresolved uh it has some really strange syntactical elements that did not exist prior to concepts being in the language. It introduces a way to declare templates without actually writing template. We already have this with generic lambdas, but it introduces it for global functions and things like that, you're able to write like a function, open parentheses,
Starting point is 00:43:28 and then a concept for the parameter name and then followed by the actual, the end declaration. That will implicitly become like a template that's constrained by that. A lot of people didn't like that. My personal problems, like all of that aside, my personal problems were a much more fundamental thing,
Starting point is 00:43:43 which is that this proposal, in my opinion, does not have any way of us getting to a place where we will be able to do concept checking of the definitions of functions prior to them being instantiated. If I could elaborate on that a little bit, right now what this concept proposal does is it's sort of a replacement for what we currently do with things like std enable if. So you have a template and you constrain it by some requirements like the specific overload of your function is just ignored when substitution takes place. But the other aspect of concepts, in my opinion, that's very important is, let's say you constrain your function by, for instance, copyability. So in other words, you require that, well, we'll say movability, you require that the type, an instance of the type that you pass to this is a movable type, but you don't necessarily state that it's a copyable type. Inside the function definition,
Starting point is 00:44:54 if you do something like copy your object, it would be nice if you'd be able to get like a compile time error for this, because you never stated in your in your requirements list that your type was able to be copied uh and i do not see for sophisticated cases how this current proposal will be able to move us in that direction for allowing that and the reason why it bothers me so much is we had a the c++ 11 proposal for concepts was very different and very integral to its whole uh definition of concepts was the the ability to do concept checking of definitions of functions and things like that and the way they did it was they actually had to change like the meaning of of what it was to be inside the definition of a constrained function it had to alter things like
Starting point is 00:45:44 how name lookup and overload resolution took place from within the body of a constrained function. It had to alter things like how name lookup and overload resolution took place from within the body of the function, which I think are completely important to doing concepts correctly. A lot of people disagree with me on this. This is one of the reasons why concepts didn't make it into C++11,
Starting point is 00:45:59 was that people thought that it was a little bit too restrictive. It's hard to go over the details verbally on the air, but there were definitely, there's a post that was made by Faisal Vali a few months ago asking about my paper in the SGA forums. And we go into, he was just asking, like, are my concerns warranted? And that ended up spawning, like, a big discussion. And I give a bunch of examples of the issues in that thread,
Starting point is 00:46:36 if anybody is really curious. But anyway, those are my specific problems with concepts today. But it's surprising that there are a lot of reasons why concepts got cut, and this is just one very, very minor one. Do you feel confident that's going to make it into C++
Starting point is 00:46:56 20? Like some of these changes that you're worried about will be made? I don't know. I think not everybody agrees that there's no path forward for function definition checking. I am pretty much convinced that there is no path forward for it. And one of the main people behind the previous iteration of concepts also shares in that opinion that it seems like there's not going to be any path forward for adding it in the future. However, the people behind concepts, a lot of them feel that there is a path forward. Although I'm hesitant, because while I personally don't see it, they also don't have a proof of concept of this in C++ that actually does it. And I, it's something that I'm not willing to take on faith right now, what this concepts does is it
Starting point is 00:47:41 adds a whole bunch of new syntax to the language. And in my personal opinion, while it's, it's cool because it's able to get rid of things like, uh, the requirement of things like std enable. If I'm, I'm worried that it's not enough of an improvement to warrant this type of, you know, vast change to the language. And if we're going to make this type of change, I want it to be done right. And I'm just really worried that we're going in the wrong direction. So my impression is that the older concepts proposal was an even more vast change to the language. And this proposal was accepted, or at least moved forward, because it was a smaller change. We added some syntax, and then, you know, it made people happy in some sense. with like an entirely new syntax and scrapping behavior is we could have just scaled back
Starting point is 00:48:45 the previous iteration of concepts and doug gregor who's one of the main people behind the previous iteration um wrote a paper on this a few years ago unfortunately it was mostly ignored because we were already moving forward with concepts light which is just we could have just scaled back all the effort that we did in the previous uh, eliminated a lot of the things that people consider too complex, eliminated a lot of the controversial stuff. But unfortunately, that did not go over that well. And a lot of the people who are behind the previous iteration of concepts are no longer active in the community. Like Doug, for instance, is now he's at Apple, and he works on the Swift programming language, which is an absolutely fantastic programming language. And I sort of wish that he had not left the C++ community. But
Starting point is 00:49:36 that's that's kind of the state that we're in. So in my opinion, part of part of the reason why we're moving forward with this iteration of concepts is just we don't have anybody really championing um what i personally consider to be better concepts um and that's kind of why we're here but okay okay but that said there's like i i actually do like this iteration of like for all the negative things that i say i actually do like this iteration of concepts i like all the work that andrew is doing i'm just worried that i really just being truthful i don't see it being um having a path forward for for being the type of language feature that we want it to be or that a lot of people expect it to be which is something that will be able to you know check the definitions of your functions at the time you write your function templates prior to them being instantiated. Makes sense. As a standards committee member, are there any features that didn't make it
Starting point is 00:50:32 into C++17 that you think should have? I really wish that we had some form of default comparisons. I do agree that there were problems with what we currently had in the proposal that was moving forward. And it's unfortunate that we couldn't make it work. I think that having something akin to default comparisons is really important to the language. It makes code so much easier to write. And it makes working with makes code so much easier to write. And it makes working with like
Starting point is 00:51:06 generic algorithms so much easier, because if you don't have to manually write things like comparison operators yourself, you know, on your own, and the default actually works, people are going to be using things like standard algorithms much more frequently, because, you know, it doesn't require them doing more boilerplate. Yeah, I can totally see that. Yeah. But yeah, so if anything, I would say, yeah, default comparisons. I wish we had something like that in 17. But I'm also really confident we will have something like that in C++ 20.
Starting point is 00:51:38 So if people can hold off a little bit, we'll get there. I never read the proposal for that, but I kind of assume operator know operator equals equals operator less than and then we would have like you could do equals default equals delete if you wanted to just like other default operations so part of part of the problem with with this proposal or part of one thing that a lot of people had that a lot of people took issue with was that it wasn't um it wasn't opt-in it was opt-out right so in other words uh it's not like if you didn't let's say you have an existing type uh it automatically will have a an equality operator after this change assuming it meets all the other
Starting point is 00:52:20 requirements uh as opposed to you having to opt in and say equals default. And so this actually changes, it has the ability to change existing types, which is is a little bit scary. And it can even change the meaning of existing code, which is also kind of scary. So a lot of people really did not like that. I will say that this is one of those things where like, if we were designing SQL plus from from scratch, I think everybody would want, you know, operator equals equals to be defined by default, and you wouldn't have to opt in for it. But a lot of the hesitation comes from the fact that, you know, we're not starting from scratch, we have the language as it as it is today.
Starting point is 00:53:01 And we have to be very careful to not change the meaning of programs in very subtle ways from standard to standard. And it's kind of an unfortunate thing. But it's a valid concern. Right? Maybe to finish off, you're also on the program committee for C++ Now. Do you know if there's going to be a call for speakers soon or any other news you might want to share so yeah uh so it's people supposed now 2017 it's the week of may 15th may 15th to may 20th uh we do we have not yet put out a uh a uh call for papers call for proposals for talks but uh we expect to do that either by the end of this year so very soon or the beginning of next year. So it should be coming very soon. We also haven't announced keynote speakers yet, but we have some great stuff planned. Awesome.
Starting point is 00:53:52 And for people who aren't familiar with C++ Now, it's a small conference in Aspen. It originally started off as BoostCon back in, I think, 2006. This is the 11th year it changed the name to c++ now i think four or five years ago and uh it's a much smaller conference than uh than cpp con i i think it's it's a much more interesting con uh conference in that i think that there's a much higher percentage of people who are attending who are like members of the standards committee or boost library authors and things like that and uh it's you really get a chance to to talk to people at the conference who are on the standards committee and if you're like ever if you're ever curious about why things in the language are a certain way and uh if if you just happen to be in the lounge like in the in the middle of the conference you can just talk to anybody you want. Like, like Sean parent is frequently there. Not that I'm not that I'm advertising that Sean parent,
Starting point is 00:54:49 you know, like it's, it's just really, it's a really fantastic conference and I can't, I can't say anything but the best about it. And I'm not just saying that as somebody who's on like the, the, the program committee for it. It's just, it really is just an amazing, amazing conference. It's a great venue also. Yeah, Aspen is absolutely awesome. I've been encouraging the members of my C++ users group that they want to go also, because it's an easy drive from Denver.
Starting point is 00:55:17 Okay, well, Matt, where can people find you online? Do you have a blog or Twitter or anything? My Twitter is cppsage. I don't have a blog or anything. anything? My Twitter is CPP Sage. I don't have a blog or anything. Maybe I should make a blog. Okay. Well, thank you so much for your time today. Thank you for having me.
Starting point is 00:55:34 Thanks for joining us. Thanks so much for listening in as we chat about C++. I'd love to hear what you think of the podcast. Please let me know if we're discussing the stuff you're interested in. Or if you have a suggestion for a topic, I'd love to hear about that too. You can email all your thoughts to feedback at cppcast.com. I'd also appreciate if you like CppCast on Facebook and follow CppCast on Twitter. You can also follow me at Rob W. Irving and Jason at Leftkiss on Twitter. And of course, you can find all that info and the show notes on the podcast website

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