And even without the multiplicative increase from those terms, there's still a dozen or more, is it?
Jason TurnerYeah, and there's the ones, again, no one thinks about these. So copy assignment operator. Your options are by value, const reference by value, by reference, const reference, volatile reference, or const file tile reference. That's for the parameter, right? The right hand side of the argument. But you can also reference, you can L-value reference or r value reference qualify it. So that's three different states there, because unqualified, L-value, or r value reference qualified. And then you can also qualify it as const volatile, const volatile or unqualified, right?
ConorRecorded on October 7th, 2026. My name is Connor, and today with my co-host Ben, we chat with Jason Turner in part two of this three-part conversation. In today's episode, we talk about Jason Turner's rule of N talk that he gave both at CPPCon and NDC Tech Town. Well, maybe we should talk about some of these talks. I know that Ben had specifically called out this rule of N, which I'm assuming is uh alluding to the rule of one, three, five. Although it could be a different rule that happens to be. It is? Okay, so maybe I'm not sure, Ben, if you have a question or or Well, why don't we ask Jason first?
BenWhat is the rule of n? What that what is what does the talk cover?
Jason TurnerThe talk I wanted to give kind of a modern update on like the rule of zero and five, basically, right? And like, well, okay, Ben, you don't like I think this is fair to say, you don't like things that are default constructible. Is that a safe-ish?
BenI don't like I was thinking about this this morning in preparation for our conversation today. And yeah, let's go with that. I have a whole lot to say on that, but let's let's park that for a moment.
Jason TurnerSo at the very least, you have opinions and you think, look, if your thing's gonna be default constructible, there should be a reason why it's default constructible. Is that fair? I think that's fair. For sure. Okay. For sure. But most people don't even don't think about default constructability, right? So I'm just like, okay, so let's talk about, let's take it to the rule of six, right? Which you don't like, okay, if you go look at Howard Hinnett's like articles on this stuff, yeah, he talks about the default constructor also as one of the special member functions, because it is one of the functions that the compiler will create for you if you don't do anything to get in its way. And you know, okay, so I just thought I would do that. And then I'm like, well, like I kind of want to make sure that I I forget what road I went down, but I'm like, I kind of want to make sure that I cover like all the possible things that can impact the rule of five, right? So for the sake of our listeners, if you write a destructor, copy constructor, move constructor, copy assignment, or move assignment operator, then those impact the other special member functions that are generated. So if you provide a copy operation, then the compiler does not generate for you the move operations. But if you provide the move operations, one or the other, then the copy operations are implicitly deleted. And there's like a big difference between not provided and deleted, right? Like this anyhow. So I started to go down this rabbit hole, and I'm like, well, what are all the different signatures that the compiler thinks is a copy?
BenOne of the special member functions?
Jason TurnerYes.
BenOkay.
Jason TurnerAnd I think well now I have to double check this. That was I have to Oh shoot, I have to go back and look at my numbers.
BenBecause there are constra so just to restate what you just said, there are, for example, considering copy construction. Yes. There are you can write the copy constructor signature in potentially a number of different ways that the compiler will know that yes, this is considered the copy constructor.
Jason TurnerYes. And the copy constructor itself has well, if you you can you can default arguments on the copy constructor. Let's just throw that topic away, because you have infinitely many copy constructors if you can default them. So whatever. Ignore that. But most people don't know that there are actually our crap, I'm gonna get these numbers wrong. There's a lot of signatures that are count as distinct overloads that the compiler will count as copy constructor. So it is, it is non-const reference, which no one thinks about, of the same type.
BenRight. The parameter is a non-constructs.
Jason TurnerRight, non-const reference, which is famous.
BenSo the regular one is the parameter is a const reference. That would be the one most people reach for.
Jason TurnerThat's what most people would reach for, but the compiler is willing to generate one for you that takes a non-const reference.
BenOkay.
Jason TurnerIn the case that the subobjects of your type themselves have copy constructors that take non-const references. The compiler is going to generate one for you that takes a non-const reference. Oh, right. No one thinks about that, right? So non-const reference, const reference, volatile reference, const file tile reference. Those are the valid copy constructor signatures, the things that are actually different overloads, right? And move constructor.
BenBut that can be expressed also as a template, perhaps, or there are other ways to write.
Jason TurnerNo, if you make it a template, then it does not impact the rule of five. It has to be a non-template function. As far as the generation of the other.
BenIt can be no except or otherwise.
Jason TurnerIt can be no except, but that is a distinct type, but that does not affect overload resolution. So I kind of tried to focus a little bit on like what things specifically affect overload resolution. But if you include a no accept, so I don't know how far we want to go into this, but like spoiler alert for the copy assignment operator, that if you include also constexper, const eval, no except, and I think no discard or not, something like that. There's 320 different ways of spelling a copy assignment operator that the compiler will count for you as you provided a copy assignment operator. And like, what?
BenRight. And even without the multiplicative increase from those terms, there's still a dozen or more, is it?
Jason TurnerYeah, and there's the ones again, no one thinks about these. So copy assignment operator. Your options are by value, const reference by value, by reference, const reference, volatile reference, or const file tile reference. That's for the parameter, right? The right hand side of the argument. But you can also reference, you can L-value reference or r value reference qualify it. So that's three different states there, because unqualified, L value, or r value reference qualified. And then you can also qualify it as const volatile, const volatile or unqualified, right? Whatever the multiplication is.
BenTo be fair, qualifying qualifying an assignment as const has niche value only. You tend to see it in DSLs, I'm gonna say in DSLs.
Jason TurnerWell, but someone in the audience pointed out that stdignore does that.
BenOkay, yeah. Good example from the library.
ConorYeah. So does this mean that that Howard Hinnant table that anyone that's seen I don't know, there's a number of talks that reference it. I don't actually think I saw the original Howard Hinnant table. I just it floats around in the C community. Is what you're saying is that like there's a higher dimensional version of that. Yes. Where all of these qualifiers, and so like if you thought that table was bad, that is but the surface of like, it's not even like a hypercube, it's whatever, an n-dimensional thing where these things interact. And is that the point of your talk that like hold my beer, you think that table's bad? Like it's it's way worse than that?
Jason TurnerWell, that wasn't it wasn't the point of my talk. That's just where I started and then accidentally went down this ridiculous rabbit hole. I I've spent, I don't know, on the order of probably over 40 hours of research on this talk, and I never expected that to happen. Like I just kept going. Like, what is happening? And then the point of the, okay, so the point of the, oh, let's just do a modern take on that. But then I also wanted to add the spaceship operator in because the spaceship operator has its own concerns. Like it's not a special member, and that the compiler will never generate something, a comparison operator for you unless you ask it to. But it can. So then I started playing with the rules of okay, what things can be defaulted or not. And just for the record, you can default the reference qualified assignment operators, and you can default the you can default the copy constructor that takes a non-const reference, and you can default the copy assignment operator that takes a non-const reference. Both of those can be defaulted unexpectedly. Anyhow, this and now it's like too much information in my head. Now like if a student asks me a question about one of these things, I'm just like, and then I try to go into simplified mode because it's now too much.
BenAll right. You were getting to the point that aside from special members now, since C20 and seemingly continuing, the compiler is now able to generate more functions like equality, like spaceship, like maybe postfix increment, is it in C27?
Jason TurnerIn C'est 29. In C29, that was approved. Postfix increment, postfix decrement can be defaulted if you provide the prefix versions of those. But the other rabbit hole I went down is like, okay, say you explicitly equals default the spaceship operator. What does that give you? And this has becomes like a trick question. Unexpectedly. No, no, no, if you explicitly.
BenWell.
Jason TurnerUh-huh. The return type is its depends.
BenSo yes. So it would be member wise spaceship. Yes. And the return type would depend on the return type of the spaceship on the subobjects in some way. Correct. But let's say I mean the easy version is like if they all have the same return type. But it's some common type of of those particular.
Jason TurnerYeah, it's the common type of the return types of the sub-objects, results of their spaceship operators. But I'm not even worried about that part. I mean like you have the spaceship operator, you've equals defaulted it. Let's just say hypothetically you wanted to take a pointer to the less than operator. Can you?
BenOh. Well, the less than operator doesn't exist, so maybe no?
Jason TurnerIt doesn't exist. I don't know. You're gonna now tell us. Yeah, so the less than operator. You can still take it's what is the actual wording? It is usable.
BenOkay.
Jason TurnerOkay. Can you take the pointer.
BenYou can write the expression a less than b.
Jason TurnerRight. Okay. Can you take a pointer to the equality operator?
BenWell, I don't know. And if the answer is different from can you take a pointer to less than a sort of thing. It is different.
Jason TurnerOf course it is, right? Because if you explicitly default to the spaceship operator, the equals operator is implicitly defaulted. But the rest of them are usable. I'm doing air quotes for those of you who can't see me. They're usable in air quotes. Alright. So the if you if you have an equals operator available in code that was pre-C20, and now you compile it in C20 mode, you implicitly get not equals. That's neat. Thank you, C20, for implicitly giving me not equals.
ConorYeah.
Jason TurnerBut that implicitly available not equals, that is also usable. That is not actually existing, right? So I can't, I can't take a pointer to the not. Anyhow, it was this rabbit hole that just kept getting deeper and deeper and deeper. And so you might have reasons for explicitly defaulting all six equality operators. Yeah, uh yes, all the comparison operators. You might have a reason for explicitly defaulting them all if you want them to be like actually exist, not just usable.
BenRight.
Jason TurnerIt's just oh, I don't know.
BenSo what's the answer to the question? So what is the answer to the question? Can you take a pointer to operator less than if you have defaulted operator spaceship?
Jason TurnerOh no, no, you can't. Sorry. That function doesn't exist. You can't.
BenYou can't. Okay.
Jason TurnerYou can use it, but you can't take a pointer to it.
BenI see. Yeah. Yeah, because the compiler's not generating that function, it's doing something like rewriting expressions or trying correct rewrites of expressions.
Jason TurnerIt rewrites it, yeah. And just in case anyone's curious, if you do explicitly default it and then you take a pointer to it and you call it, it is internally going to call the spaceship operator and then and then check to see if it was less than.
BenRight. Okay. So the compiler's implementation of that equals default would would route to the spaceship.
Jason TurnerBut you can't default, like if I wanted only less than, hypothetically, I cannot just equals default that. I have to equals default the spaceship. And then what I would actually have to do is equals default spaceship and then explicitly delete the other ones if I wanted the compiler generated less than, hypothetically. The talk just became a giant rabbit hole. That's all. Like there's just so many little nuanced details to this that I had no idea. And it was an interesting ride.
BenYeah, I uh I I may have released some of the rabbits on Jason a couple of months ago. The talk when you were because because when Jason said, you know, I'm thinking about doing this rule of n, modern take, I said, and something I had recognized in coming in my code is a lot of times I followed the rule of zero, right? Which is just a lot of things are just plain structs, and it's the rule of zero. But equality is important in a lot of places where you have so effectively it becomes the rule of one. You want to provide equality.
Jason TurnerAnd which can be the same.
BenOne of the rabbits that that that dug this war in. Yeah.
Jason TurnerThat's right. Yes. Yes, you did that, you caused part of that problem, and then you caused the rest of the problem when you asked me something about whether or not they can be if the right hand side can be, or the left hand, whatever, if the if the operator itself can be const qualified or something. You you brought that up, and I said, oh crap. Oh there's like a multiply of three for all of these now, again. Yeah.
ConorAnyhow, what was the reaction in the in the audience after you'd given the talk?
Jason TurnerI think it was a good reaction at CBP Con. I gave the talk at CBPCon and DC Type and N D C Type Town. I think it did a better job at C BPCon, and I feel like it was a good reaction. I think it made people think. And I think one of the main like practical things that that came out of this, and I've talked to other people about it since then, is like if you have something like a strong wrapper around a floating point type, there's a very real possibility that you would want to explicitly default the spaceship and then explicitly delete the equality operator because that's considered problematic anyhow. So make your make your user of your library do something more explicit. Just I don't know. The the the the the TLDR of this thing is like think before you write code, people. You know.
BenI mean, yeah exactly. This whole thing. I have a class in my code base which deals with wraparound. Right? So it's the original use case was like you have a you have a microcontroller, it has a 32-bit unsigned register that is time that is continually incrementing microseconds, let's say. And of course that can wrap around, and you when you measure time, you need to know what's in the past and what's in the future. You need to account for that wraparound. Oh right. And so quite reasonably I wanted a class that could encapsulate that, and so the the comparison operators on the class do the appropriate thing for the wraparound of the unsigned value, right? And for the for that class, I delete operator less than. Right? I c I spell it differently. I have like I think I call it CumpLess or something. But I delete operator less than, the reason I do that is that when you have a wraparound semantic like that, your less than operator is no longer transitive. Right. Right? Because it's like rock, paper, scissors, right? It's non-transitive. And that means that if you naively pass it to Yeah, you know, A beats B, B beats C, C beats A. Right? If you have a wraparound space, your less than operator is of that form. Which means that if you try and sort things naively with std sort, you're passing it a comparator that does not does not adhere to what it requires. Right. Which means you have technically have undefined behavior at that point.
Jason TurnerYeah, see I'm fully on board with this, and I think that's a perfect example. Like, yeah, think. Like it doesn't make sense to just blindly provide all of the operators. Selectively delete some if that would make sense for your problem set. Or maybe selectively enable only the couple that do make sense for your domain. And also, like I'm a I have had a recent discussion with other friends about this, and they many of them disagree with me, because they're like, oh well, everyone knows if you provide the other constructors that you don't get a default constructor. And I'm like, you know what? No, I've reached the point in my life where if I don't want the thing default constructible, I'm gonna explicitly default, delete that default constructor. Always. You know, like explicitly delete the default constructor. Don't let don't make, don't require the reader of your code to know all of the intricacies of how the special member functions are generated. Be explicit.
BenRight. Or zoom because as you've just talked about and demonstrated, that is a very deep rabbit warren. It's a warren, it's not just a hole. It's a whole not just the hole, it's a whole network of tunnels.
ConorIt's a whole civilization under there. What is Warren? W-A-R-R-E-N?
Jason TurnerYeah.
ConorYeah, you know, where rabbits live. That's a new word, a new word.
Jason TurnerI have to be honest, I only know that word because I read the Kevin and Kell comic strip. It's old. It's been around forever.
ConorI don't know that. I was gonna say that's not cal that's not a different word for Calvin and Hobbes, is it?
Jason TurnerNo. Kevin and Kel is probably the I think they advertise themselves as the oldest webcomic, oldest continuous webcomic. I don't know. I discovered it maybe, I don't know, 15 years ago or something, and I went back and I read the entire archive. So I've I've read now all holy crap, 31 years of it? Oh my god.
BenI was gonna say, if it's if it's the oldest webcomic, it must have started the mid-90s.
Jason Turner95, yeah. Good gracious. That's before Connor was born. No, no.
ConorNot quite good. I was I was but a wee lad back then. But um Warren, I'll add a I'll add a I don't know, dictionary link to some dick online dictionary for those that are in my in my camp. I was watching an interview the other day on Jon Stewart, and he kept on throwing out these words, and I was like, if I was the inner being interviewed, I would have to ask every second question. Like, sorry, can you define that? Like I felt so bad for the I assume the interviewee. Uh his vocabulary was larger than mine, but I can't remember a couple of the words.
BenI was like But John Stewart was being unnecessarily recondite and sesquipadalian.
ConorOkay, well, Ben would have gone toe-to-toe. He would have come back with that big word and said that stuff. I definitely don't have those in my uh dictionary or vocabulary either. Or definitely in my dictionary, not in my vocabulary. What were the two words you just said? Recondite and something. I was joking. Sesquipedalian? Sesquippedalian, is that a fake word?
BenNo, no. I think it means prone to using long words. Oh, I thought I thought. In extreme form, it runs to uh hippopotter monstrous sesquippedalian, I believe.
ConorWow. When you said you were joking, I thought you meant like it was super califragilistic, expialidocious, like that kind of thing, like a made-up word, but no, you were joking, but they're real world words. Uh alright. Well, listener, there'll be a couple more dictionary entries if you want to look at some online dictionary definition of. I'm not gonna try and pronounce the second one or the third one. That was Impressive. Impressive uh I guess that's what you have those ever come up in your what are they called?
BenOh no, these are just things you learn uh uh from a lifetime of geeking out on word games and things like that.
ConorI was gonna say, yeah, does this come up in cryptics?
BenLike, because that's probably uh Well, long words don't tend to come up in crosswords very much because they just no. There are you know, a crossword is at maximum, and the crossword entry is fifteen, a crossword grid is fifteen by fifteen as a standard. So you don't tend to get very long In fact, it's rare to get even a fifteen letter. Usually top out about eleven, twelve, maybe thirteen.
ConorBe sure to check these show notes either in your podcast app or at adspthepodcast.com for links to anything we mentioned in today's episode, as well as a link to a GitHub discussion where you can leave thoughts, comments, and questions. Thanks for listening. We hope you enjoyed and have a great day. I am the anti brace.
BenUm