使用编译时已知的类型避免模板详细程度和动态多态性

时间:2013-08-22 14:30:35

标签: c++ templates inheritance c++11 polymorphism

在我的collision/game physics engine中,我允许用户创建/指定首选的空间parititioning方法和首选的解决方法。

以下是空间分区的示例。

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.

有没有办法隐藏 Grid2DImpulseRes类型?只有在创建World时才需要知道它们。但是Body也必须知道这些类型,因为它需要引用空间分区方法实例和解析方法实例。

所需的代码示例:

World world1{new World<Grid2D, ImpulseRes>(...)};
Body& body1{world1.createBody()}; 

void useBody(Body& mBody) { ... }     

3 个答案:

答案 0 :(得分:1)

我认为你想要的是一个很好的老式typedef

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

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

答案 1 :(得分:1)

您可以使用

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

template <class TBody>
void useBody(TBody& mBody) { ... } 

答案 2 :(得分:0)

我不知道你的代码是如何分区的,但如果你在实例化body1之后声明你的函数,也许你可以使用decltype

auto& body1 = world1.createBody();

using body_type = decltype(body1);

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