2013-08-22 1 views
0

В моем 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) { ... }  

ответ

1

I думаю, что вы хотите, это хороший старомодный typedef.

typedef basic_world<grid2d, impulse_res> world; 
typedef basic_body<world> body; 

world world1(...); 
void useBody(body& bdy) { ... }; 
0

Я не знаю, как распределял ваш код, но если вы объявляете вашу функцию после инстанцирования body1, может быть, вы могли бы использовать decltype:

auto& body1 = world1.createBody(); 

using body_type = decltype(body1); 

void useBody(body_type& b) { ... } 
1

Вы можете использовать

template <class TGrid, class TImpulse> 
void useBody(Body<TGrid, TImpulse>& mBody) { ... } 

или

template <class TBody> 
void useBody(TBody& mBody) { ... } 
Смежные вопросы