views:

193

answers:

2

I have the following data structures:

struct fastEngine { ... }
struct slowEngine { ... }

template<typename T>
class Car {
   T engine;
   vector<T> backupEngines;

   virtual void drive() = 0;
}

class FastCar : public Car<fastEngine> {
   virtual void drive() {
      // use the values of "engine" in some way
   }
}

class SlowCar : public Car<slowEngine> {
   virtual void drive() {
      // use the values of "engine" in some way
   }
}

Car* getCarFromCarFactory() {  // 1
   if (randomNumber == 0)
      return new FastCar();
   else
      return new SlowCar();
}

void main() {
   Car* myCar = getCarFromCarFactory(); // 2
   myCar->drive();
}

The compiler complains at locations 1 and 2 because it requires that I define Car* with template parameters. I don't care what templated version of Car I'm using, I just want a pointer to a Car that I can drive. The engine structs must be structs because they are from existing code and I don't have control over them.

+11  A: 

You could create a non-templated base class that Car<T> inherits, e.g.

struct ICar {
    virtual void drive() = 0;
};

template <typename T>
class Car : public ICar {
    // ...
}

int main() { // BTW, it's always `int main`, not `void main`
    ICar *myCar = getCarFromCarFactory();
    myCar->drive();
}
PiotrLegnica
It's ugly being forced to have another interface, but it works. Thanks a ton!
Brian
+1 same answer I would give
messenger
@Brian: The whole point of the interface is to minimize the exposed surface area of the class (i.e. encapsulating away the templating). Since it doesn't look like you need to know the type of the engine in the class using the car, it is more clean to hide that information.
messenger
+1  A: 

PiotrLegnica's answer is right, but I'd just like to add a few points:

class templates are not classes

In your code, Car is a class template. A class template is not a class, it is only ... a template from which classes can be defined, and different instantiations of a same template do not necessarily lead to types having the same interface. A simple example:

template<class T>
class Foo
{
public:
  T Bar();
  bool Baz(const T&);
};

struct and class is (almost) the same thing

The engine structs must be structs because they are from existing code and I don't have control over them.

I assume that you wrote this because you were suspecting that the problem was related to the use of structs instead of classes as template parameters. This is not the case. In C++, struct and class is almost the same thing. The only difference is that the default access and inheritance are public with a struct while they are private with a class.

Éric Malenfant