对模板运算符的未定义引用,其定义位于同一头文件中

Undefined reference to template operator with definition in same header file

本文关键字:定义 于同一 文件 运算符 引用 未定义      更新时间:2023-10-16

我在尝试使用我编写的模板化运算符时收到来自 clang++ 的链接器错误。

错误是:

main.cpp:(.text+0xfe): undefined reference to `operator<<(std::ostream&, schematic<130ul, 128ul, 130ul> const&)'
main.cpp:(.text+0x28c): undefined reference to `operator<<(std::ostream&, schematic<130ul, 1ul, 130ul> const&)'

现在,在我继续或将其标记为重复之前:我知道您不能将模板定义放在单独的.cpp文件中,我没有这样做。运算符的定义位于一个单独的头文件中,该文件包含在带有声明的头文件中,如本答案中所述。由于它仍然给我链接器错误,所以我在这里问。

法典

主.cpp

// includes
int main(int argc, char const* argv[])
{
// ...
switch (/* call */)
{
case /* one */:
fout << mapArtFlat(/* ctor params */).exportScematic();
break;
case /* another */:
fout << mapArtStaircase(/* ctor params */).exportSchematic();
break;
}
return 0;
}

示意图.h

#ifndef SCHEMATIC_H
#define SCHEMATIC_H
// includes
template <std::size_t W, std::size_t H, std::size_t L>
class schematic
{
friend std::ostream& operator<<(std::ostream&, const schematic<W,H,L>&);
// class things
};
// output operator
template <std::size_t W, std::size_t H, std::size_t L>
std::ostream& operator<<(std::ostream&, const schematic<W,H,L>&);
// ...
#include "schematic_cpp.h"
#endif

schematic_cpp.h

// ...
// output operator
template <std::size_t W, std::size_t H, std::size_t L>
std::ostream& operator<<(std::ostream& lhs, const schematic<W,H,L>& rhs)
{
// lot of code involving external libraries and processing data from the object
}
// ...

我尝试过的事情

  • 注释掉 schematic.h 中的operator<<声明
  • 使operator<<内联

您的示例大部分有效,无法重现您遇到的错误。仍然发现了应该改变的东西。

首先,您不能在尚未声明的函数上声明友谊。您需要将模板operator<<声明放在类定义之前。但是,当您尝试这样做时,您会意识到需要声明原理图类,因为它是函数类型的一部分。转发声明该类,您应该没问题:

template <std::size_t W, std::size_t H, std::size_t L>
class schematic;
template <std::size_t W, std::size_t H, std::size_t L>
std::ostream& operator<<(std::ostream&, const schematic<W,H,L>&);
template <std::size_t W, std::size_t H, std::size_t L>
class schematic {
// ... stuff ...
};

其次,您需要显式声明要声明为朋友的函数的模板参数(或声明您与每个模板参数的每个函数都是朋友(。您可以像这样这样做:

template <std::size_t W, std::size_t H, std::size_t L>
class schematic
{
friend std::ostream& operator<<<W,H,L>(std::ostream&, const schematic<W,H,L>&);
// ... class stuff ...
};

如果修复这些不能解决您的问题,请尝试发布您遇到的问题的完整最小可重现示例。您的链接问题可能与由于您在实现中执行的操作而被丢弃的模板实例化有关。

相关文章: