Templates and generic programming
T.3
Use templates to express containers and ranges
Reason
Containers need an element type, and expressing that as a template argument is general, reusable, and type safe. It also avoids brittle or inefficient workarounds. Convention: That's the way the STL does it.
Example
template<typename T>
// requires Regular<T>
class Vector {
// ...
T* elem; // points to sz Ts
int sz;
};
Vector<double> v(10);
v[7] = 9.9;
Example, bad
class Container {
// ...
void* elem; // points to size elements of some type
int sz;
};
Container c(10, sizeof(double));
((double*) c.elem)[7] = 9.9;
This doesn't directly express the intent of the programmer and hides the structure of the program from the type system and optimizer.
Hiding the void* behind macros simply obscures the problems and introduces new opportunities for confusion.
Exceptions: If you need an ABI-stable interface, you might have to provide a base implementation and express the (type-safe) template in terms of that. See Stable base.
Enforcement
- Flag uses of
void*s and casts outside low-level implementation code