2013-09-26 6 views
1

У меня много проблем с преобразованием основанного на полиморфизме физического механизма, который я написал на основе шаблонов. Раньше я занимался абстрактным классом SpatialBase (пространственное воспаление) и абстрактным классом ResolverBase (решатель контактов). Но эти два класса всегда были известны во время компиляции, так почему бы не templatize движок и не удалить накладные расходы виртуального вызова?Циркуляр шаблона зависимости типа для физического движка

Ну, вот проблема:

template<class TS, class TR> class World; - это World<TS, TR> класса, TS является пространственным типом разбиения и TR типа контакта решателя.

template<class TS, class TR> class Body; - это класс Body<TS, TR>. Он должен знать как TS, так и TR, потому что он хранит 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>.

Есть ли способ решить это? Или я обречен использовать полиморфизм во время выполнения навсегда?

ответ

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; 
} 
+0

Я хочу, чтобы пользователь моего физического движка решил, какой метод пространственного разделения и какой метод решения контактов использовать во время компиляции. –

+0

@VittorioRomeo: вы можете сделать 'World' шаблоном, который принимает шаблонные аргументы. – jxh

+0

Я не понимаю, как это могло бы помочь, так как я должен был бы сказать «ImpulseSolver >>' –

0

Класс кузова не обязательно должен быть шаблоном. Вы можете использовать указатель вместо ссылки, например World<TS, TR>*, и вперед объявить TS и TR в заголовке Body.

2

вы можете использовать policy-based design, чтобы создать класс, который уже использует сетку и импульсный решатель. , то вы можете использовать crtp для связи между ними.

Если вы дадите простой код, я могу сделать простой пример. используйте значащие имена, а не TS и TR. Например, используйте grid_type и solver_type.

Я делаю то же самое в своей научной симуляции. Я делаю класс гамильтониана, который берет адаптер в систему координат и адаптер к методу в качестве политик.

Update (1)

Вам также может понадобиться использовать точные using сек, но идея здесь:

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 { 
}; 
+0

Примером может быть очень полезно - я напишу код –

+0

Вот минимальная ситуация - надеюсь, что это достаточно хорошо: http://pastie.org/8358341 –

+0

+1 за предложение CRTP. – jxh

Смежные вопросы