Вопрос о шаблонном дизайне C ++ - PullRequest
3 голосов
/ 05 апреля 2011

У меня есть модель, написанная на C ++, которая основана на полиморфизме времени выполнения и виртуальных функциях.Модель отлично работает как есть.Я хотел бы исследовать преобразование этого в шаблоны и полиморфизм во время компиляции.Причины таковы:

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

Здесьэто упрощенный гипотетический пример того, как моя модель выглядит сейчас:

class Particle
{
public:
  // ...
  virtual void move();
};

class Electron : public Particle  { /*...*/ };


// Physics Models /////////////////////////////////

class PhysicsModel
{
public:
  // ...
  virtual void doStuffWithParticles();
private:
  Particle* theParticle;
};

class NewtonPhysics : public PhysicsModel  { /*...*/ };
class QuantumPhysics : public PhysicsModel  { /*...*/ };


// SimulationModels ////////////////////////////

class SimulationModel
{
public:
  virtual void runSimulation();
  // ...
private:
  PhysicsModel* thePhysics;
  Particle* theParticle;
};

class HadronCollider : SimulationModel { /*...*/ };

Но скажите, если я хочу встроить функции Particle, например move(), потому что это внутренний цикл из ряда for-циклови может значительно выиграть от бонуса скорости.И во время компиляции я знаю, какую физическую модель и имитационную модель я использую, но Particle - это решение во время выполнения.

Итак, как насчет:

template <typename TParticleType>
class PhysicsModel
{
  // ...
  TParticleType theParticle;
};

template <typename TParticleType,
          typename TPhysicsModelType>
class SimulationModel
{
  TParticleType theParticle;
  TPhysicsModelType theModel;
};

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

int main()
{ 
  // ...
  switch( getUserInput()->currentParticleType )
  {
     case ELECTRON:  HadronSimulation<Electron, QuantumPhysics>.run();
     case PROTON:    HadronSimulation<Proton, QuantumPhysics>.run();
     // ...
  }
}

... и предпочел бы поместить тип "QuantumPhysics" в другое место, чтобы он просто находился в том же месте.Это упрощенный пример, и на самом деле у меня будет около 4-5 параметров, которые являются решениями во время компиляции.

По сути, я ищу дизайн, который позволил бы мне вписать параметр времени выполнения в подобный шаблонный фреймворк.Есть ли хороший способ сделать это?Извиняюсь, если это кажется идиотским вопросом, но я совершенно новичок в шаблонах на C ++.Заранее спасибо.

Ответы [ 2 ]

1 голос
/ 05 апреля 2011

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

template< class Particle >
class HadronSimulationGenerator {
public:
   typedef HadronSimulation< Particle, QuantumPhysics > type;
};

int main()
{ 
  // ...
  switch( getUserInput()->currentParticleType )
  {
     case ELECTRON:  HadronSimulationGenerator<Electron>::type.run();
     case PROTON:    HadronSimulationGenerator<Proton>::type.run();
     // ...
  }
}

Не намного красивее.

0 голосов
/ 05 апреля 2011

Как вы исправили свои PhysicsModel и ParticleType в первом примере (без шаблонов)? Был ли конструктор ответственным за создание обоих экземпляров? Если да, то вы можете использовать похожую технику, чтобы скрыть это от пользователя, выполнив switch в конструкторе SimulationModel.

class SimulationModel {
    void run() {
        switch(currentPhysicsMode) {
        case QUANTUM:
            switch(currentParticleType) {
                case ELECTRON:
                    SimulationModelImpl<Electron, QuantumPhysics>::run();
                    break;
                case PROTON:
                    SimulationModelImpl<Proton, QuantumPhysics>::run();
                    break;
                ...
            }
        }
    }
};

template <typename TParticleType,
      typename TPhysicsModelType>
class SimulationModelImpl {
    TParticleType theParticle;
    TPhysicsModelType theModel;
    ...
};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...