Let me explain what I am asking for by an example. Imagine I have a class for a car.
Now, the car may have a lot of extras:
- 4 doors instead of only 2
- Automatic door locking
- 4 Wheel drive
I want to create the class with any combination of these options. Any of these options needs some data members. Imagine the class now looks like this:
class Car {
public:
bool FourDoors;
bool AutomaticDoorLocking;
bool FourWheelDrive;
Door doors[4]; //4 only needed if FourDoors=true
DoorLockingElectronic doorElectronic; //Only needed if AutomaticDoorLocking=true
TransmissionsShafts[4]; //4 only needed for FourWheelDrive=true
void lockDoors() {
if (AutomaticDoorLocking) {
doorElectronic.lockDoors();
} else {
// Do manual door locking
}
}
};
So far so good, but now I want to create a lot of cars, so many that memory gets critical. And I do not need most of the extras in most of those cars.
I could create a base class, and derive classes with those options enabled or disabled.
But I would have to create 2^{#extras} classes to create all possible combinations, with a lot of double code.
So I thought maybe templates could be used? (that is the question).
I can imagine having a flag template, and rewrite the lockDoors like this:
template<int flags>
void Car<flags>::lockDoors() {
if (flags | AutomicDoorLockingFlag) {
doorElectronic.lockDoors();
} else {
// Do manual door locking
}
}
Wonderful! But the class Car<0> still takes a lot of unnecessary space. So:
Can I somehow include or exclude class members depending on a template parameter?
Other Ideas how to deal with the situation are also welcome!
You want to use policy classes:
Put all the policy specific stuff (e.g.
lockDoors()function) inside the policy classes rather than theCarclass. TheCarclass inherits these, which is a form of composition (i.e. you are building all their functionality into theCarclass).Note that you should give all the policy classes a
protected, non-virtualdestructor so that they can only be instantiated as part of a derived class.You then instantiate customised cars in the normal template manner:
Of course, you can use
typedefs to help with this (and template aliases in C++0x will help a lot, too).See: Policy-based Design