Хотя это не подходит ни для одной ситуации, шаблоны могут дать вам "типизированную утку во время компиляции" .
Допустим, у вас есть два типа вектора:
struct Vec3A {
float x, y, z;
};
struct Vec3B {
float p[3];
};
Вы можете определить шаблоны функций, которые скрывают реализацию получения компонентов:
template<class T> float get_x(const T&);
template<class T> float get_y(const T&);
template<class T> float get_z(const T&);
template<> float get_x<Vec3A>(const Vec3A& v) { return v.x; }
// ...
template<> float get_x<Vec3B>(const Vec3B& v) { return v.p[0]; }
// ...
С такими помощниками вы можете теперь написать универсальные функции, которые работают на обоих:
template<class T> float length(const T& t) {
return std::sqrt(std::pow(get_x(t), 2),
std::pow(get_y(t), 2),
std::pow(get_z(t), 2));
}
Вы также можете продолжить, специализируя такие утилиты, как length()
, для повышения производительности или по другим причинам, например. если определенный вектор уже имеет функцию-член, предоставляющую вам длину:
template<> float length<Vec3C>(const Vec3C& v) {
return v.length();
}