对模板运算符的未定义引用,其定义位于同一头文件中
Undefined reference to template operator with definition in same header file
我在尝试使用我编写的模板化运算符时收到来自 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 ...
};
如果修复这些不能解决您的问题,请尝试发布您遇到的问题的完整最小可重现示例。您的链接问题可能与由于您在实现中执行的操作而被丢弃的模板实例化有关。
相关文章:
- 有没有什么方法可以使用一个函数中定义的常量变量,也可以由c++中同一程序中的其他函数使用
- 虚拟成员函数的定义是否强制在同一转换单元中动态初始化静态数据成员?
- C++17 和更新的 std::分配器是否适用于动态数量的自定义堆?
- 您可以将binary_search应用于具有自定义类型的矢量吗?
- 定义一个 void f(void) 函数,但使用来自同一范围的变量?
- 如何定义依赖于参数包转换的函数的返回类型
- FBString 的小字符串优化是否依赖于未定义的行为?
- "... already defined in *.obj"但我没有在同一范围内两次定义任何变量
- 同一系统上的自定义和默认提升库
- 如何转发声明依赖于变量定义的类,而变体定义又依赖于模板化类?
- 如何定义具有依赖于符号调试的参数的函数
- 为什么 std::vector 适用于类定义中的不完整类型?
- 我如何使用explicit模板实例化用于类定义中定义的模板成员函数
- 如何正确地将规则 5(或零?)应用于包含带有字符串的自定义对象向量的类
- 如何从同一个头文件中定义 2 个类,而一个类依赖于另一个类
- std::memory_order_relaxed 相对于同一原子变量的原子性
- 当我以不同方式定义对同一变量的引用时,结果不同
- 依赖于同一值的多个static_assert
- 如何知道TCP连接是否存在于同一机器上的两个进程之间
- 为什么不能定义在同一文件中前向声明的成员函数?