0

I have an exercise wherein I must use a template class "Garage" that takes as parameters either a "car" or a "bike". Easy enough but I keep getting errors since I obviously don't understand the templates well enough. Is this :

template<class Car>
class Garage{
    Car array[10];
public:
    void addCar(int counter1);
    void removeCar(int counter1);
    void displayContents(int counter1);
};

template<class Motorbike>
class Garage{
    Motorbike array[10];
public:
    void addMotorbike(int counter2);
    void removeMotorbike(int counter2);
    void displayContents(int counter2);
};
 

proper ? Do I have to insert the template infront of every function of the class ? The program of course contains more classes and functions but its the template thing I need to get sorted out in my head. Thanks for taking the time.

463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185

2 Answers2

6

If you had to write out specifically every implementation for each instantiation then there would be no need for templates in the first place. You could name your classes CarGarage and MotorbikeGarage and call it a day. You probably want something along the line of this:

template<class VehicleType>
class Garage{
    VehicleType array[10];
public:
    void addVehicle(int counter1);
    void removeVehicle(int counter1);
    void displayContents(int counter1);
};

From this class template (it is not a template class, there are no template classes. Garage is a template, not a class) you can instantiate the types Garage<Car> which has an array of Cars as member and a Garage<Motorbike> which has an array of Motorbikes as member.

Implementations of the member functions need to be in the header (see Why can templates only be implemented in the header file?). And it is easiest to define them inline within the template.

463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185
0

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);
Richard Chambers
  • 16,643
  • 4
  • 81
  • 106