A template is a way of being able to write code once for a general type, creating a template usable for multiple specific types, then request that the compiler use the template to generate source code for one or more specific variable type(s). Templates are a way to provide compile time polymorphism (see what is the difference between templates and polymorphism as well as Template Polymorphism not Working? and Templates polymorphism) allowing you to use the same code with different variable types with the compiler generating the type specific code for you.
In your case you have two specific variable types, Car
and MotorBike
, and you want to write a template definition that expresses the same algorithm for each of these two types that allows the compiler to generate the type specific source code. See also Difference of keywords 'typename' and 'class' in templates?
template<typename Vehicle, size_t nSize = 10>
class Garage {
Vehicle array[nSize]; // storage space for the vehicles
public:
void addItem(Vehicle &v, int counter) { if (counter < nSize) array[counter] = v; }
void removeItem(int counter);
void displayItem(int counter);
};
And you would use this template definition to create a Garage
variable for each of the vehicle variable types, Car
and MotorBike
.
Garage<Car> myCarGarage; // default number of cars
Garage<MotorBike, 12> myBikeGarage; // we own more motorbikes than cars
And then use these new garage variables to manage either your cars or your motorbikes.
MotorBike b1, b2, b3;
Car c1, c2, c3;
// ...
myCarGarage.addItem(c1, 4);
myBikeGarage.addItem(b1, 2);
Note: A template may place requirements on a variable type definition that is used with the template. For example in your case if you are storing a Car
into the Garage
, the class Car
will need to be able to support assignment into an array of Car
.
Note: std::vector
would probably be a more appropriate choice for storage rather than an array. The use of the standard containers such as std::vector
is usually much more convenient and robust and reliable than old style arrays.
A bit of background
I think of a template as being a kind of stencil or stamp that allows me to write the code for an algorithm which I then ask the compiler to insert into my source code using a specific type. The stencil or stamp, the algorithm, has the design and I can then pick the color, the variable type, I want to use with that design.
A template definition must be visible by the compiler at the place where the template definition is being used. This means that in most cases the template definition is in a header file which is included into the C++ source files where the template is used. However if a template is local to a single C++ source file and the template definition is only used in that source file, there is no reason why the template definition isn't just put into the C++ source file. The only requirement is that a template definition and any dependencies of the template definition must be visible by the compiler at the point where the template definition is being used.
A template definition is used by the compiler to generate source code when the compiler finds a place where the template definition is being used. A template definition that is not used, is ignored. If the template definition is used with several different variable types then source code is generated for each different variable type using the same template definition.
C++ uses templates with the various containers such as std::vector
so that the generalized vector container class can be used with any type as long as the type definition is written to support the requirements of std::vector
.
Most common examples of templates are class templates in which the template is used to describe a class
the way you are using it. However it doesn't have to be a class
but can also be a function. Here is a very short example of a function template.
template<typename Thing>
Thing funcThing(Thing x) {
return x + 1; // requires that object class supports adding 1 to object value
}
And this template would be used with the following syntax:
class Thing1 {
int myData;
public:
Thing1(void) : myData(0) {}
Thing1(int x) : myData(x) {}
// the function template funcThing() requires class using it to support addition.
Thing1 & operator + (int x) { myData += x; return *this; }
};
// ....
float ax = funcThing<float>(2.0);
int jx = funcThing<int>(4);
float bx = funcThing<float>(ax);
Thing1 x1(4), x2;
x2 = funcThing<Thing1>(x1);