为什么这个c++;代码未在g+中编译+;4.8.2 我试图用G+4.4.2(Ubuntu 14.04环境)编译C++脉冲棋引擎[0 ]。
我在链接阶段遇到以下错误:为什么这个c++;代码未在g+中编译+;4.8.2 我试图用G+4.4.2(Ubuntu 14.04环境)编译C++脉冲棋引擎[0 ]。,c++,c++11,g++,C++,C++11,G++,我在链接阶段遇到以下错误: Linking CXX executable pulse- CMakeFiles/pulse.dir/main.cpp.o: In function `pulse::MoveGenerator::MoveGenerator()': /home/user/cpp/movegenerator.h:15: undefined reference to `pulse::MoveList<pulse::MoveEntry>::MoveList()' libcore.
Linking CXX executable pulse-
CMakeFiles/pulse.dir/main.cpp.o: In function `pulse::MoveGenerator::MoveGenerator()':
/home/user/cpp/movegenerator.h:15: undefined reference to `pulse::MoveList<pulse::MoveEntry>::MoveList()'
libcore.so: undefined reference to `pulse::MoveList<pulse::MoveEntry>::rateFromMVVLVA()'
libcore.so: undefined reference to `pulse::MoveList<pulse::RootEntry>::sort()'
libcore.so: undefined reference to `pulse::MoveList<pulse::RootEntry>::MoveList()'
libcore.so: undefined reference to `pulse::MoveList<pulse::MoveEntry>::sort()'
collect2: error: ld returned 1 exit status
我得到输出
0000000000000000 W _ZN5pulse8MoveListINS_9MoveEntryEE4sortEv
0000000000000000 W _ZN5pulse8MoveListINS_9RootEntryEE4sortEv
使用4.9.1时,但使用4.8.2时无输出
为什么g++4.9.1生成排序函数而4.8.2不生成,这是编译器中的错误还是pulse源代码中的错误?
编辑:
正如在指出的重复问题“为什么模板只能在头文件中实现?”中所述,我不明白,它在g++4.9.1中是如何工作的?
移动列表标题:
#include "value.h"
#include "move.h"
#include <array>
#include <memory>
namespace pulse {
/**
* This class stores our moves for a specific position. For the root node we
* will populate pv for every root move.
*/
template<class T>
class MoveList {
private:
static const int MAX_MOVES = 256;
public:
std::array<std::shared_ptr<T>, MAX_MOVES> entries;
int size = 0;
MoveList();
void sort();
void rateFromMVVLVA();
};
class MoveVariation {
public:
std::array<int, Depth::MAX_PLY> moves;
int size = 0;
};
class MoveEntry {
public:
int move = Move::NOMOVE;
int value = Value::NOVALUE;
};
class RootEntry : public MoveEntry {
public:
MoveVariation pv;
};
}
#包括“value.h”
#包括“move.h”
#包括解决方案
将以template类开头的两行移到源文件的末尾
解释
此源使用显式模板实例化(14.7.2)。只要在整个程序中只使用模板的显式实例化,就可以在源文件中(而不是在头文件中)定义模板。在这种情况下,它们将是MoveList
和MoveList
但是,有一个问题:显式专门化必须出现在模板定义之后(14.7.2/4)
函数模板、变量模板、类模板的成员函数或静态数据成员或类或类模板的成员函数模板的声明应在该实体的显式实例化之前进行。类模板、类模板的成员类或类或类模板的成员类模板的定义应在该实体的显式实例化之前,除非显式实例化之前有具有相同模板参数的实体的显式专门化
g++4.9为什么不强制执行这一点,谁也猜不透。@0x499602D2停止如此激烈地挥舞那把受骗锤,伙计!如果不了解sort()方法在何处被调用以及如何调用,就不可能回答这个问题。我看不到在本问题中包含的代码示例中调用sort()的位置。请将以template class
开头的两行移到源文件的末尾。重复的q不适用,您实际上可以在源文件中定义模板(有时)。@SamVarshavchik,我在第64行的movegenerator.cpp中包含了指向github存储库的链接,sort被调用。@n.m.,它起了作用,尽管我不太明白为什么,这一切都是在头文件或源文件中定义的模板。
#include "value.h"
#include "move.h"
#include <array>
#include <memory>
namespace pulse {
/**
* This class stores our moves for a specific position. For the root node we
* will populate pv for every root move.
*/
template<class T>
class MoveList {
private:
static const int MAX_MOVES = 256;
public:
std::array<std::shared_ptr<T>, MAX_MOVES> entries;
int size = 0;
MoveList();
void sort();
void rateFromMVVLVA();
};
class MoveVariation {
public:
std::array<int, Depth::MAX_PLY> moves;
int size = 0;
};
class MoveEntry {
public:
int move = Move::NOMOVE;
int value = Value::NOVALUE;
};
class RootEntry : public MoveEntry {
public:
MoveVariation pv;
};
}
#include "movelist.h"
#include <cassert>
namespace pulse {
template class MoveList<MoveEntry>;
template class MoveList<RootEntry>;
template<class T>
MoveList<T>::MoveList() {
for (unsigned int i = 0; i < entries.size(); ++i) {
entries[i] = std::shared_ptr<T>(new T());
}
}
/**
* Sorts the move list using a stable insertion sort.
*/
template<class T>
void MoveList<T>::sort() {
for (int i = 1; i < size; ++i) {
std::shared_ptr<T> entry(entries[i]);
int j = i;
while ((j > 0) && (entries[j - 1]->value < entry->value)) {
entries[j] = entries[j - 1];
--j;
}
entries[j] = entry;
}
}
/**
* Rates the moves in the list according to "Most Valuable Victim - Least Valuable Aggressor".
*/
template<class T>
void MoveList<T>::rateFromMVVLVA() {
for (int i = 0; i < size; ++i) {
int move = entries[i]->move;
int value = 0;
int piecetypeValue = PieceType::getValue(Piece::getType(Move::getOriginPiece(move)));
value += PieceType::KING_VALUE / piecetypeValue;
int target = Move::getTargetPiece(move);
if (Piece::isValid(target)) {
value += 10 * PieceType::getValue(Piece::getType(target));
}
assert(value >= (PieceType::KING_VALUE / PieceType::KING_VALUE)
&& value <= (PieceType::KING_VALUE / PieceType::PAWN_VALUE) + 10 * PieceType::QUEEN_VALUE);
entries[i]->value = value;
}
}