Добавление методов в класс не увеличивает объекты этого класса. Методы хранятся один раз для всего класса и используются при вызовах для любых экземпляров. Поэтому добавление функций в класс GameState не приведет к тому, что алгоритму потребуется больше памяти.
В этом случае для шаблона функции потребуется только один параметр GameState
, а классы, используемые в качестве этого параметра, потребуются для реализации правильных методов.
Более гибкий подход заключается в простом использовании свободных функций в алгоритме:
template<class GameState>
int alphaBetaMax(GameState g, int alpha, int beta, int depthleft) {
if (endGame(g)) {
return 1;
}
std::vector<Move> moves = getMoves(g);
// ...
}
Здесь endGame
и getMoves
являются зависимыми именами, они зависят от параметра шаблона (так как они принимают g
в качестве параметра). Поэтому компилятор не будет искать фактические определения этих имен при объявлении шаблона (он еще не знает, какой тип должны иметь эти функции, поскольку GameState
еще не указан).
Только при создании экземпляра шаблона должны быть доступны перегрузки для этих функций, которые соответствуют способу их использования в шаблоне:
struct MyGameState {};
bool endGame(const MyGameState &st) {
return false;
}
std::vector<Move> getMoves(const MyGameState &st) {
// ...
}
void tst() {
MyGameState s;
alphaBetaMax(s, 1, 1, 1); // uses the new functions
}
Таким образом, вы можете адаптировать любой объект GameState к вашему алгоритму, не требуя специальных методов для этих объектов. Чтобы не загрязнять глобальное пространство имен этими новыми функциями, вы можете поместить их в свое собственное пространство имен или класс свойств.
Таким образом, вы можете просто пропустить дополнительные параметры шаблона, если функции правильных имен и типов будут определены после создания шаблона.