So templates so far have been templates of one meta argument. But there's actually no restriction. But keep in mind that most of what you wanna do is templates of one argument. Once you start multiple argumentative templates, you get into horrendous complexity, unneeded complexity in most cases. It's a prescription for doing fairly dangerous things, that are unanticipated. But, in some cases they're useful, and so it's desirable to know how to use it. And when to use it, so again warning, be careful. You really have to understand when you need more of these, typically metatypes. Well let's see a situation where maybe that would be reasonable. Here is code with a two templates. And it's a copy routine. So, wee wanna copy some source data. Into some destination data, and we don't necessarily want, we could have this as all T, but that would mean that the copy would have to be for example an integer array copied to an integer array. And let's notice a couple things about this code. First off, in the signature, the source argument is const. So we have a little bit of const correctness. We're indicating to the user, to the reader, to the compiler, don't modify the source array. Not true for the destination array obviously. That's what we want done. We want the destination array yo have a copy of the source array. And again, we have a variable size that's how much to be copied. And for the moment it's conceivable that we would have a default. But it's probably not that useful to have a default in this. There wouldn't be some standard default that would be used more than some very specific value. So it would not make sense to say size here is a hundred, that would be unusual. And then the other critical thing here, we're doing is this safe casting, and this is what, in my mind, makes this a not unreasonable routine. Because if I don't have a safe cast for type T1, Casting the object of type T2, then, when this code runs. Is going to be an error. If no safe casting. Or the compiler will recognize that it doesn't have a safe cast opportunity and provide you a compile time error. In any case, the code won't work. And it won't work in a manner that will be easily detected. And in cases in which it will work we know that we have a safe way to massage the source contents into the destination contents. So what would be a safe thing? If I had integer data and I wanted to turn it into double data, that would be perfectly reasonable here, or vice versa. Both kinds of conversions, one is called a promotion, taking the data and the integer domain, and turning it into double. And the other's called a demotion. But both are conventionally well understood, handled by the safe conversion routines, and largely portable. The program as is should work, regardless of what computer system it's being run on. So here is a multiple use of a template arguments that is not unreasonable. This brings up the question of casting. Again type safety, that's a big improvement in the C world, in the C++ world over the C world. And one way that the C world was very loose with types is in that world you can say things like. Double with some kind of expression. Now whatever this expression was, the C compiler said, force that expression to be interpretable as a double. Whether that was portable or not portable. Since there were different characteristics and C++ actually, C++ is with wider range of programming including object oriented programming in which. Certain types and type hierarchies, in the old community, these are called polymorphic types, inheritance structures, have other kinds of conversion opportunities that are well understood. You get into a much richer sense of conversion opportunities in the C++ world. And you have to be far more careful about it, so C plus plus defines four basic types of conversion. The safe cast type is static cast, but then highly unsafe is reinterpret cast, that's sort of what's going on here. Sort of that corresponding. But it's alerting you to the fact that, gee, for whatever reason, which is probably a hack, which is, in my view, something you shouldn't do. If I was your manager this would be a no. You would really have to convince me that there's a good reason to do a reinterpret there. I would be extraordinarily reluctant to be using that. And then, again, in most instances for me, this was also a no. You can cast away const-ness. Sometimes you want something that was set to be const to not be const, so you would make it modifiable. But in my sense, you're mixing up two characteristics. Why did you make it const in the first place? So you're really saying, I'll make that thing mostly const. I don't want pi to all of a sudden change. I don't wanna say, gee, It's going to be pi, but there may be some time I wanna tweak that, it's just not how I'm gonna think. So again, most of these other kinds of casts, you basically be throwing out of your repertoire. Safe casting is okay, the old style casting, while available in many compilers is deprecated. Deprecated means, don't use it, the compiler writer is at liberty of actually denying its use. And then there are some special cases where class hierarchies involve dynamic casting, where when you're doing some very fancy object oriented programming this may be required. But again I'm not a fan, so I would say safe casting, yes. And the others are largely no.