嘗試編譯下面的檔案時會發生此錯誤:
錯誤
Logging.h: In instantiation of 'void Sudoku::printBoardWithCandidates(const Sudoku::Board<BASE>&) [with int BASE = 3]':
Logging.h:10:64: required from here
Logging.h:10:64: error: explicit instantiation of 'void Sudoku::printBoardWithCandidates(const Sudoku::Board<BASE>&) [with int BASE = 3]' but no definition available [-fpermissive]
template void printBoardWithCandidates<3>(const Board<3>& b);
^
由于我在 C 方面不是很有經驗,因此我看不出有任何可能導致此問題的原因。由于定義存在于 .cpp 檔案中,我看不出有任何不編譯的理由。有人介意向我解釋一下嗎?
.h 檔案
#pragma once
#include "Board.h"
namespace Sudoku
{
template<int BASE>
void printBoardWithCandidates(const Board<BASE> &b);
template void printBoardWithCandidates<2>(const Board<2>&);
template void printBoardWithCandidates<3>(const Board<3>&);
template void printBoardWithCandidates<4>(const Board<4>&);
}
.cpp 檔案
#include "Logging.h"
#include <iostream>
template<int BASE>
void Sudoku::printBoardWithCandidates(const Board<BASE> &board)
{
// definition...
}
編輯:我在整個程式中多次使用了類似的實作。例如 Board.h
#pragma once
#include <vector>
#include <cstring>
#include "stdint.h"
namespace Sudoku
{
struct Cell
{
int RowInd;
int ColInd;
int BoxInd;
friend bool operator==(const Cell& cell1, const Cell& cell2);
};
bool operator==(const Cell& cell1, const Cell& cell2);
template<int BASE>
class Board
{
public:
static constexpr int WIDTH = BASE * BASE;
static constexpr int CELL_COUNT = WIDTH * WIDTH;
static constexpr uint16_t CELL_COMPLETELY_OCCUPIED = 65535 >> (sizeof(uint16_t) * 8 - WIDTH);
private:
const int EMPTY_VALUE;
uint16_t rowOccupants[WIDTH] = {0};
uint16_t colOccupants[WIDTH] = {0};
uint16_t boxOccupants[WIDTH] = {0};
int* solution;
void Init();
void Eliminate(Cell& cell, uint16_t value);
public:
std::vector<Cell> EmptyCells;
Board(const int* puzzle, int* solution, int emptyValue = -1);
void SetValue(Cell cell, uint16_t value);
void SetValue(Cell cell, int value);
int* GetSolution() const;
inline uint16_t GetOccupants(Cell cell) const
{
return rowOccupants[cell.RowInd] | colOccupants[cell.ColInd] | boxOccupants[cell.BoxInd];
}
};
template class Board<2>;
template class Board<3>;
template class Board<4>;
} // namespace Sudoku
uj5u.com熱心網友回復:
問題在于,在您提供3 顯式模板實體化的頭檔案內部,相應成員函式模板的定義printBoardWithCandidates不可用。因此,編譯器無法為這些實體生成定義并給出提到的錯誤說:
error: explicit instantiation of 'void Sudoku::printBoardWithCandidates(const Sudoku::Board<BASE>&) [with int BASE = 3]'
but no definition available [-fpermissive]
^^^^^^^^^^^^^^^^^^^^^^^^^^^
有兩種方法可以解決這個問題,如下所示。另請注意,我使用了一個空結構Board,因為Board您提供的類非常大(長度)并且如果在此處粘貼 2 次將占用大量空間。不過這個概念是一樣的。
方法一
在提供 3 個顯式模板實體之前,在標題中提供成員函式模板的定義,printBoardWithCandidates如下所示:
頭檔案.h
#pragma once
#include "Board.h"
namespace Sudoku
{
//note this is a definition
template<int BASE>
void printBoardWithCandidates(const Board<BASE> &b)
{
}
//this will work now because the compiler have the definition available above
template void printBoardWithCandidates<2>(const Board<2>&);
template void printBoardWithCandidates<3>(const Board<3>&);
template void printBoardWithCandidates<4>(const Board<4>&);
}
板子.h
#pragma once
template<int>
struct Board
{
};
主檔案
#include <iostream>
#include "header.h"
int main()
{
return 0;
}
作業演示
方法二
這里我們提供了成員函式模板的定義以及源檔案中的 3 個顯式模板實體化。在頭檔案中,我們只提供成員函式模板的宣告,頭檔案中沒有提供顯式模板實體化。
頭檔案.h
#pragma once
#include "Board.h"
namespace Sudoku
{
//this is a declaration not a definition
template<int BASE>
void printBoardWithCandidates(const Board<BASE> &b);
//no explicit template instantiation here since we have provided only the declaration above and not the definition
}
板子.h
#pragma once
template<int>
struct Board
{
};
原始碼.cpp
#include "header.h"
//provide the definition here
template<int BASE>
void Sudoku::printBoardWithCandidates(const Board<BASE> &board)
{
// definition...
}
template void Sudoku::printBoardWithCandidates<2>(const Board<2>&);
template void Sudoku::printBoardWithCandidates<3>(const Board<3>&);
template void Sudoku::printBoardWithCandidates<4>(const Board<4>&);
主檔案
#include <iostream>
#include "header.h"
int main()
{
return 0;
}
作業演示
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/478099.html
