代码之家  ›  专栏  ›  技术社区  ›  Vittorio Romeo

物理引擎的循环模板类型名称依赖关系

  •  1
  • Vittorio Romeo  · 技术社区  · 12 年前

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

    问题来了:

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

    template<class TS, class TR> class Body; -这是 Body<TS, TR> 班这需要两者都知道 时间 TR公司 因为它存储了 World<TS, TR>& .

    template<class TR> class Grid; -这是 Grid<TR> 班它需要知道 TR公司 因为它需要知道 Body<Grid, TR> 是(它存储存储实体的单元格)。

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

    现在看到问题了吗?声明正确是不可能的 世界<TS、TR> !

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

    这是一个循环依赖。空间分割类需要了解接触解算器类,反之亦然,因为两者都需要知道 身体<TS、TR>

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

    3 回复  |  直到 12 年前
        1
  •  3
  •   jxh    12 年前

    您可以定义 World 成为一个将模板作为参数(而不是类型)的模板。然后,您可以重新定义 Body 以及解析要参数化的方法类模板 世界 .

    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;
    }
    
        2
  •  2
  •   kirill_igum jfriend00    12 年前

    你可以使用 policy-based design 制作一个已经使用网格和脉冲解算器的类。 那么你会使用 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 {
    };
    
        3
  •  0
  •   Zac Wrangler    12 年前

    Body类不需要是模板。你可以使用指针而不是像这样的引用 World<TS, TR>* 并在Body的报头中转发声明TS和TR。