Templates and generic programming
T.84
Используйте нешаблонную основную реализацию для обеспечения ABI-стабильного интерфейса
Причина
Повышение стабильности кода. Предотвращение раздувания кода.
Пример
Это может быть базовый класс:
struct Link_base { // stable
Link_base* suc;
Link_base* pre;
};
template<typename T> // templated wrapper to add type safety
struct Link : Link_base {
T val;
};
struct List_base {
Link_base* first; // first element (if any)
int sz; // number of elements
void add_front(Link_base* p);
// ...
};
template<typename T>
class List : List_base {
public:
void put_front(const T& e) { add_front(new Link<T>{e}); } // implicit cast to Link_base
T& front() { return static_cast<Link<T>*>(first)->val; } // explicit cast back to Link<T>
// ...
};
List<int> li;
List<string> ls;
Теперь существует только одна копия операций связывания и отвязывания элементов List. Классы Link и List занимаются исключительно манипуляцией типами.
Вместо отдельного «базового» типа ещё одним распространённым приёмом является специализация для void или void*, а общий шаблон для T представляет собой безопасно инкапсулированные приведения к базовой реализации void и обратно.
Альтернатива: используйте реализацию через Pimpl.
Контроль
???