您将如何在模板中定义未定义的函数?
我正在编写一个 C++ 项目,并且在类模板中有一个通用的评估方法。
我唯一的问题是如何定义 generateAllMoves
和 isPosFinal
以便在使用该类模板的类中定义它?
我读到使用纯虚函数是不行的。我也不想让它静态。
我预见自己会将其重写为抽象类,但最终会遇到需要泛型类型的问题。
#ifndef ENGINE_H
#define ENGINE_H
#include <map>
using namespace std;
template< class M, class P >
class Engine {
public:
Engine() { };
struct Move {
P move;
P pos;
int score;
};
Move evaluate( P position ) {
Move best;
if ( posIsFinal( position ) ) {
Move newMove;
newMove.pos = position;
newMove.score = 1;
return newMove;
}
else {
map< M , P > allMoves = 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;
}
}
};
#endif
编辑:为了让大家更清楚!
我有两个不同的游戏,它们定义了自己的generateAllMoves 和isPosFinal 方法。它们使用不同的算法并返回不同的类型......例如,我很快就会实现一个国际象棋游戏,但现在我正在实现 nim。两者对移动和该位置最终的解释不同。
第二次编辑:
最终代码编译!
#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
I'm writing a C++ project and have a generic evaluate method in a class template.
My only question is how would I define the generateAllMoves
and isPosFinal
so that it is defined inside the classes that use this class template?
I've read that using pure virtual functions is a no no. I also do not want to make it static.
I foresee myself rewriting this as an abstract class, but then I would end up with a problem that requires generic types.
#ifndef ENGINE_H
#define ENGINE_H
#include <map>
using namespace std;
template< class M, class P >
class Engine {
public:
Engine() { };
struct Move {
P move;
P pos;
int score;
};
Move evaluate( P position ) {
Move best;
if ( posIsFinal( position ) ) {
Move newMove;
newMove.pos = position;
newMove.score = 1;
return newMove;
}
else {
map< M , P > allMoves = 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;
}
}
};
#endif
Edit: To be more clear for everyone!
I have two different games right that defines its own generateAllMoves and isPosFinal methods. They use different algorithms and return different types.... For example, I will be soon implementing a chess game, but right now I'm implementing nim. Both interpret move and is this position final, differently.
2nd Edit:
Final code compiles!
#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
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
做到这一点的一个好方法是使用“奇怪的递归模板参数”习惯用法。
请参阅此处了解更多信息。
A good way to do just this is to use the "Curiously Recursive Template Parameter" idiom.
See here for more information.
您可以为引擎创建一个具有所有必要参数化的特征类:
现在您可以通过定义适当的特征类来自定义您的引擎:
或者您也可以使您的引擎客户端类成为引擎特征:
当然您可以改变直接传递的内容作为引擎模板参数以及要移动到单个 traits 类的内容,例如:
You could make a traits class with all necessary parameterization for the Engine:
Now you can customize your engine by defining appropriate traits class:
Or you can make your engine client class to be engine traits as well:
And surely you can vary what is passed directly as Engine template parameters and what to move to a single traits class, e.g.:
不是特别是朋友的朋友函数,但是像这样的函数怎么样:
Not particularly a friend of friend functions but how about something like this: