Как вы будете определять неопределенные функции в шаблоне? - PullRequest
2 голосов
/ 19 октября 2011

Я пишу проект на C ++ и у меня есть общий метод оценки в шаблоне класса.

Мой единственный вопрос: как бы я определил generateAllMoves и isPosFinal, чтобы он определялся внутриклассы, которые используют этот шаблон класса?

Я читал, что использование чисто виртуальных функций - нет, нет.Я также не хочу делать это статичным.

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

У меня есть две разные игры, которые определяют свои собственные методы generateAllMoves и isPosFinal.Они используют разные алгоритмы и возвращают разные типы .... Например, я скоро буду реализовывать игру в шахматы, но сейчас я реализую nim.Оба интерпретируют ход, и эта позиция является окончательной, по-разному.

2nd Edit:

Финальный код компилируется!

#ifndef ENGINE_H
#define ENGINE_H

#include <map>

using namespace std;

template< typename Derived, class M, class P >

class Engine {

public:

  struct Move {
    P move;
    P pos;
    int score;
  };

  Move evaluate( P position ) {

    Move best;      

    if ( static_cast<Derived*>(this)->posIsFinal( position ) ) {
      Move newMove;
      newMove.pos = position;
      newMove.score = 1;
      return newMove;
    }

    else {

      map< M , P > allMoves = static_cast<Derived*>(this)->generateAllMoves( position );

      typename map< M , P > :: iterator it;

      for (it = allMoves.begin(); it != allMoves.end(); it++ ) {
        Move next = evaluate(it->second);

        if (next.score > best.score ) {
          best.pos = next.pos;
          best.move = next.move;
          best.score = next.score;
        }
      }
      return best;
    }
  }

  bool posIsFinal( P position ) {
    cerr << "Generic posIsFinal\n";
    exit(1);
  }

  map< M , P > generateAllMoves( P position ) {
    cerr << "Generic generateAllMoves\n";
    exit(1);
  }

private:


};

#endif

Ответы [ 3 ]

2 голосов
/ 19 октября 2011

Хороший способ сделать это - использовать идиому «Любопытно рекурсивный параметр шаблона».

См. здесь для получения дополнительной информации .

1 голос
/ 19 октября 2011

Вы можете создать класс черт со всей необходимой параметризацией для Движка:


template< class EngineTraits >
class Engine {

  typedef typename EngineTraits::P_type P;
  typedef typename EngineTraits::M_type M;

public:

  Engine() { };  

  struct Move {
    P move;
    P pos;
    int score;
  };

  Move evaluate( P position ) {

    Move best;      

    if ( EngineTraits::posIsFinal( position ) ) {
      Move newMove;
      newMove.pos = position;
      newMove.score = 1;
      return newMove;
    }

    else {
      typedef typename EngineTraits::moves_mapping_type MovesMapping;
      MovesMapping allMoves = EngineTraits::generateAllMoves( position );

      typename MovesMapping::iterator it;

      for (it = allMoves.begin(); it != allMoves.end(); it++ ) {
        Move next = evaluate(it->second);

        if (next.score > best.score ) {
          best.pos = next.pos;
          best.move = next.move;
          best.score = next.score;
        }
      }
      return best;
    }
  }
};

Теперь вы можете настроить свой двигатель, определив соответствующий класс черт:


struct my_engine_traits
{
  typedef <em>some-type</em> P_type;
  typedef <em>some-type</em> M_type;
  typedef std::map<M_type, P_type> moves_mapping_type;

  static bool posIsFinal(P_type const &position)
  {
    // ...
  }

  static moves_mapping_type generateAllMoves(P_type const &position)
  {
    // ...
  }
};

Или вы можете сделать так, чтобы ваш клиентский класс двигателя также был характеристикой двигателя:


class my_engine_client
{
  typedef <em>some-type</em> P_type;
  typedef <em>some-type</em> M_type;
  typedef std::map<M_type, P_type> moves_mapping_type;

  static bool posIsFinal(P_type const &position)
  {
    // ...
  }

  static moves_mapping_type generateAllMoves(P_type const &position)
  {
    // ...
  }

  typedef Engine<my_engine_client> Engine;
  Engine m_engine;  
};

И, конечно же, вы можете изменять то, что передается непосредственно в качестве параметров шаблона Engine, и что перемещать в один класс traits , например ::


template< class M, class P, class PositionProcessor >
class Engine {
// ...
};

0 голосов
/ 19 октября 2011

Не особенно друг друга, но как насчет этого:

template< class M, class P >
class Engine {
public:
  friend void generateAllMoves(P position);
  void evaluate( P position )
  {
    ...
    generateAllMoves(position);
    ...
  }
};

// here your specific function

void generateAllMoves(int position )
{ 
  ;
}

int main(int argc, char* argv[])
{
// then instantiate it
  Engine<int,int> X;

  ..
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...