So enumerated types let you have small sets of related constants. And in C++, we are going to start to see that we can do operator overloading. We can give new meanings to the already existing operators to find in the C language. So that these extended types, these new types, get to have the look and feel of the native types. And that's the secret to good OO programming. Making your extended types, your type extension natural. Making it seem like these types are native. Okay, so, critical to creating a new type, is to follow as your paradigm the behaviors of native types. Native types are types like ints and floats. And you want your created type to mimic those as much as possible. And what we're gonna do is try to use a natural type, namely the days of the week. And make that a enumerated type. And this is the central lesson of object orientation. Object orientation is a way to expand a programming language to incorporate new types that were not built into the core of the language. In the early days of programming languages, kitchen sink approaches to language is like, you know, one tried to put every type possible that could be imagined at the time into the language. And now it was just very awkward and made for ponderous language. Object orientation changed this and said let's have some techniques that let us extend the existing types in such a way that it's seamless. They look and feel like the native types. And that's what we're trying to acheive here. So, critical to that is also to be able to redefine operators, give them new definitions, for the new types. And that's what we're gonna concentrate on here. We have enumerated type, and the enumerated type has Sunday, Monday, Tuesday, Wednesday, which means that the enumerator is Sunday as explicitly value zero. And by the time you get to Saturday, Saturday would have the explicit value six. Also, notice that we have defined within this type a new meaning for the auto increment operator. Now why didn't we choose the auto increment operator? The auto increment operator when used on integer types changes the type by one. So if we had an integer type that was 100 and we auto-incremented it, we would get 101. Or if it was 107, we'd get 108. And here we want the same behavior. We want to be able to take a day of the week and say, what's the next day? We can imagine that this a routine that gets us a next day. If it's Wednesday, the next day is Thursday. And we're creating a calculus on this kind of calendar object. Which makes sense intuitively. People know what the next day is, what add one day to that day in the week is, and what the next day is that you get. Now let's look at this definition. We have inline, which we've seen. We use inline because we expect in this calculus to use this operator frequently. And we want it to not pay a high cost and efficiency, and in-line gets us that. It tells the compiler, wait a minute, try to inline this code, not to use it as a function call. We have a return type which is days. Why? Because we want to take a day like Tuesday and return a day Wednesday. We don't want to return an integer type or some other type. We could do something like that. But that wouldn't make sense. So we're taking a day and converting it to another day. And then we have a unary argument, one argument. So any time we have an operator and we do operator overloading, giving an operator a new meaning, we are constrained. One of the critical constraints is what kind of operator is it? Is it a unary operator or a binary operator? Those are the two kinds of operators you find, and C++. You're not allowed to overload the question mark, colon operator which is a ternary operator. So you only have the unary operators and the binary operators, and you can give them new meanings. If you're not using meanings on there, you can't overload them for your existing types because that would create chaos. So if it doesn't have a meaning, you can give it a new meaning. You give it a new meaning by deciding and taking explicitly what the argument is. The other thing you can't change is you can't change the precedence order of the operator. So, if you recall auto increments are very high precedence. That remains. Let's see the actual semantics. The actual semantics say at 1 casting it safely to an end. So if it was Sunday, you would add one and make it Monday, in effect. And then you would module owe it with seven. Why do you modulo it with seven? Because the next day after Saturday is Sunday. so if you added one you would get seven. Seven modulo seven is zero. See that gets you seven. So, you're really using modulo arithmetic when you talk about the calendar. So this is the right semantics. And notice it gets the return type days, so it's not creating an integer, the integer is automatically mapped back into, converted into days. Okay. Anytime we have a new type, again, this is part of our object oriented design idiom. Any time we have a new type, we would also like to have, a familiar way to do I/O, input output. Remember, the operator, which in the core language is bit shift is being used and the output of the language as a writing operator. So this is really, like in the C language, a printf. Except here we notationally want to use this typically obscure and rarely used bit shift for this other purpose. And in fact, intuitively, the arrow's going in that direction suggests output. And again, you should get used to this idiom. So there are several things I want to point out. The return type is going to be a reference to ostream, we'll see why. That's because we're going to want associativity in the output screen. The operator is a binary operator, so it needs two arguments. One of the arguments is going to be an output stream. And, the second argument is going to be the type we wanna define the output operation for. And again, these are traditionally, it makes sense, that they are called by reference. They're called by reference because the ostream, we don't want a copy. We want to directly use that ostream, for efficiency purposes, for many other reasons. We just want a referential connection to the output stream. However complicated, this turns out to be simple, so we could of just used call by value. But as I say, it's an idiom. So, keep this in mind. Most commonly, the output variable is not to be mutated. So, we can't change it, that's why we use const. And if it's something complex, we also want to call it by reference. So it's not locally copied. And then you can see the semantics are very simple. We use the switch statement, and again, this is a pneumatic for a switch statement. We do a case since these are an integral type. The numerators are integral types. Case of Sunday, let's just print out the string SUN. Alternatively, if I wasn't lazy, you might have liked to print out the full name. And once you get that case, this is the assignment the out. And then, this is what you return. You return the output stream as the value of this overloaded operator. So as they say, normally bit shift, but bit shift is very specialized, so it's not very much used. And then for any newly created type, new type that you extend, there's an expectation that you've overloaded the operator to provide a proper form of output. So now let's make use of all this in a main. We're using our new type, D. Were assigning it one of its enumerators values monday, so d is monday. And we have an uninitialized variable, days variable, e. And now, because we have extended the language, we've done operator overloading. This is really a call on the procedure operator plus plus type days. It's really calling this. Recall semantics. This is the auto increment operator. This has the right flavor. What does it mean to auto increment Monday? Add 1 to Monday, get the next day, the next day is Tuesday. So we're gonna take whatever the intrinsic representation is for Monday, which is the integral value 1, convert it to a 2. It doesn't overflow in the sense of going beyond 7, 6 actually. So, it stays 2. 2 is Tuesday, and now notice that we're also using operator overloading here. In that the first expression that gets evaluated, let me rewrite that, is cout. This is a binary expression. This expression has an ostream, and it has a days type. And we've overloaded operator bit shift to have a meaning for that. And the meaning for that is going to be d is Monday. So, we're gonna see in the string MON printed. Then this is going to return the same ostream. That ostream is the built in, standard out. So standard out get returned and now it gets combined with a tab character. So now a tab is printed on screen, however many spaces your standard tab is, and then that's evaluated and again returns the ostream standard out. And then it's evaluated with respect to the days variable e, which in this case is Tuesday. And then again we return the ostream and then we put a newline in there so that we skip to the next line. Go to the next line. So we get a natural semantics. A natural semantics for our new data type. And we've done it by overloading two operators that didn't have meaning for this. This is again critical to idiomatically understanding, even though this is a very simple type. So get it right on the simple type, and you'll be able to carry it over to a much more complex type any time you need to do type extensibility. And this is a principle in object orientation, and one of the great powers of C++ that isn't in all languages. Java, for example, doesn't have it. Is also the ability to create new semantics for the operators in terms of however you've extended whatever type extension you've undertaken. Okay, what native operator is these double less than signs? That should be apparent from what we have just learned. Can the precedence of that operator be changed? If I have a new type then maybe I want a different precedence than the underlining type. How do we know what meaning of that first operator will apply? If we now have it overloaded for very different kinds of types and arguments, which one will we choose to apply? So think about that for a sec. Well as we mentioned earlier, this is left bit shift. It remains left bit shift. We cannot change meanings in the C++ language. Where things are defined for the native type, they remain defined that way, so that can't be changed. It can't be overwritten. So, if we had as an argument an integer value shifted by 3, and if you thought of this as the binary number, that's the binary representation of 5, right so that's 1 0 1, that's 4 nothing in the 2's position, in the 1's position, in the 0's position is 1, so that's really 5. Then we shifted over 3, and now we have 1 0 1 shifted 3 positions which in decimal would be 40. So that definition remains. Precedence and associativity also cannot be changed. So, that you have to know. So, if in your domain, you're coming from something, electrical engineering, or chemistry, and you're using operators that have meaning to chemists or electrical engineers, and it was a different precedence or associativity for the operator than what is in the existing C++ language. That's something you may have to keep in mind. And then, which definition gets used is based on the binary signature. So, here a binary signature was int shift, shift, int. But mostly, you're going to see ostream bit-shift some arbitrary type. And in a case where we have ostream and where we've overloaded the ostream, the bit-shift operator with a type. Then we will have the appropriate input or output behavior, in this case of course output. For input were gonna do the same thing with right bit shift.