C++ 显式实例化模板函数会导致错误"no definition available"



当尝试编译下面的文件时,出现这个错误:

误差

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

问题是在头文件中提供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次,将占用大量空间。但概念是一样的。

方法1

在头文件中提供成员函数模板printBoardWithCandidates的定义,然后提供3个显式的模板实例化,如下所示:

header.h

#pragma once
#include "Board.h"
namespace Sudoku
{
template<int BASE>
void printBoardWithCandidates(const Board<BASE> &b)
{
//note this is a definition
}
//explicit template instantiation declaration
extern template void printBoardWithCandidates<2>(const Board<2>&);
extern template void printBoardWithCandidates<3>(const Board<3>&);
extern template void printBoardWithCandidates<4>(const Board<4>&);
} 

Board.h

#pragma once
template<int>
struct Board 
{

};

main.cpp


#include <iostream>
#include "header.h"
//explicit template instantiation 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>&);
int main()
{

return 0;
}

演示工作


方法2

这里我们提供了成员函数模板的定义以及源文件中的3个显式模板实例化。在头文件中,我们只提供了成员函数模板的声明,而没有在头文件中提供显式的模板实例化。

header.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
} 

Board.h

#pragma once
template<int>
struct Board 
{

};

source.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>&);

main.cpp

#include <iostream>
#include "header.h"
int main()
{

return 0;
}

演示工作

相关内容

最新更新