簡體   English   中英

為什么在C ++ 4.8.2中無法編譯此C ++代碼

[英]Why does this c++ code not compile in g++ 4.8.2

我正在嘗試使用g ++ 4.8.2(Ubuntu 14.04環境)編譯C ++脈沖象棋引擎[0]。

在鏈接階段出現以下錯誤:

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

當我運行命令時:

g++ -std=c++11 -c movelist.cpp && nm movelist.o | grep sort

我得到了輸出

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;
};

}

移動列表來源:

#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;
  }
}

[0] https://github.com/fluxroot/pulse/tree/master/src/main/cpp

解決方案

將以模板類開頭的兩行移動到源文件的末尾。

說明

此源使用顯式模板實例化(14.7.2)。 只要在整個程序中僅使用模板的顯式實例,就可以在源文件中(而不是在標頭中)定義模板。 在這種情況下,它們將是MoveList<MoveEntry>MoveList<RootEntry>

但是,存在一個問題:顯式專門化必須出現模板定義之后 (14.7.2 / 4)

函數模板,變量模板,類模板的成員函數或靜態數據成員或類或類模板的成員函數模板的聲明應在該實體的顯式實例化之前。 類模板的定義,類模板的成員類,或類或類模板的成員類模板的定義應在該實體的顯式實例化之前,除非該顯式實例化之前具有該實體的顯式特化對象模板參數。

任何人都猜測為什么g ++ 4.9無法強制執行此操作。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM