1

我在将我编写的基于多态的物理引擎转换为基于模板的过程中遇到了很多麻烦。我之前做的是有一个SpatialBase抽象类(空间分区)和一个ResolverBase抽象类(接触求解器)。但是这两个类在编译时总是已知的,那么为什么不模板化引擎并移除虚拟调用开销呢?

那么问题来了:

template<class TS, class TR> class World;- 这是World<TS, TR>类,TS是空间分区类型,TR是接触求解器类型。

template<class TS, class TR> class Body;- 这是Body<TS, TR>课。它需要知道两者TSTR因为它存储了一个World<TS, TR>&.

template<class TR> class Grid;- 这是Grid<TR>课。它需要知道TR,因为它需要知道什么Body<Grid, TR>是(它存储存储身体的细胞)。

template<class TS> class ImpulseSolver;- 这是ImpulseSolver<TS>。它需要知道TS,因为它需要知道是什么Body<TS, ImpulseSolver>(它直接处理身体的内部成员)。

现在...看到问题了吗?不可能宣布正确World<TS, TR>

World< Grid<ImpulseSolver<Grid<ImpulseSolver..., ImpulseSolver<Grid<ImpulseSolver<Grid... > madWorld; // not by Gary Jules.

这是一个循环依赖。空间分区类需要知道接触求解器类,反之亦然,因为两者都需要知道类的确切类型Body<TS, TR>

有没有办法解决这个问题?还是我注定要永远使用运行时多态性?

4

3 回答 3

3

您可以定义World为将模板作为参数(而不是类型)的模板。然后,您可以重新定义您的Body和解析方法类模板以由World.

template<class TWORLD> struct Body {
    Body (TWORLD &) {}
    //...
};

template<class TWORLD> struct Grid {
    Grid (Body<TWORLD> &) {}
    //...
};

template<class TWORLD> struct ImpulseSolver {
    ImpulseSolver (Body<TWORLD> &) {}
    //...
};

template <template <typename> class TS,
          template <typename> class TR>
class World {
    Body<World> body_;
    TS<World> spatial_;
    TR<World> resolver_;
public:
    typedef TS<World> SpatialImpl;
    typedef TR<World> ResolverImpl;
    World () : body_(*this), spatial_(body_), resolver_(body_) {}
    //...
};

int main () {
    World<Grid, ImpulseSolver> w;
}
于 2013-09-26T20:38:24.527 回答
2

您可以使用基于策略的设计来创建一个已经使用网格和脉冲求解器的类。然后您将使用crtp在它们之间进行通信。

如果你给出一些简单的代码,我可以做一个简单的例子。使用有意义的名称而不是 TS 和 TR。例如,使用 grid_type 和 solver_type。

我在我的科学模拟中也这样做。我创建了一个汉密尔顿类,它将一个坐标系统的适配器和一个方法的适配器作为策略。

更新 (1)

您可能还需要使用准确using的 s 但想法就在这里:

template <class body_type>
struct res_imp {
  body_type& body() {return static_cast<body_type*>(this);}
  void ri(){cout << "howdy, it's ri\n" << body().sgs;}
  string ris;
};

template <class body_type>
struct spa_g {
  body_type& body() {return static_cast<body_type*>(this);}
  void sg() {cout << "yo, it's sg\n" << body().ris;}
  string sgs;
};

template <class res_imp_type, class spa_g_type>
struct body : res_imp_type, spa_g_type {
};
于 2013-09-26T20:24:43.130 回答
0

正文类不需要是模板。您可以使用指针代替引用World<TS, TR>*,并在 Body 的标头中转发声明 TS 和 TR。

于 2013-09-26T20:10:25.490 回答