В моем collision/game physics engine я разрешаю пользователю создавать/указывать предпочтительный метод пространственного парирования и предпочтительный метод разрешения.Избегание многословности шаблона и динамического полиморфизма с типами, известными во время компиляции
Вот пример с пространственным разделением.
struct SpatialBase
{
virtual void a() = 0;
virtual void b() = 0;
...
};
struct Grid2D : public SpatialBase { ... override a() and b() ... };
struct QuadTree : public SpatialBase { ... override a() and b() ... };
struct World
{
std::vector<std::unique_ptr<Body>> bodies;
std::unique_ptr<SpatialBase> spatial;
...
World(SpatialBase* mSpatial, ...) : spatial(mSpatial), ... { }
};
auto world1{new World{new Grid2D{...}, ...}};
auto world2{new World{new QuadTree{...}, ...}};
Это прекрасно работает, но динамический полиморфизм совершенно не нужен. Факт таков: шаблонная версия World
будет слишком многословной, так как также должен быть указан метод разрешения, и класс Body
должен знать об этом.
Пример:
auto world1{new World<Grid2D, ImpulseRes>(...)}; // fine
auto& body1{world1.createBody()}; // still fine
void useBody(auto& mBody) { ... }
// illegal! Wish I could use auto& here.
void useBody(Body<Grid2D, ImpulseRes>& mBody) { ... }
// legal - but verbose, and what if the user decides to change
// spatial partitioning or resolution? All code would break.
Есть ли способ шкурой в Grid2D
и ImpulseRes
типов? Их нужно знать только тогда, когда создается World
. Но Body
также должен знать эти типы, так как ему нужна ссылка на экземпляр метода пространственного разбиения и экземпляр метода разрешения.
Желаемый пример кода:
World world1{new World<Grid2D, ImpulseRes>(...)};
Body& body1{world1.createBody()};
void useBody(Body& mBody) { ... }