仅使用标头实现的重复符号
Duplicate symbols with header only implementation
我有一个在头文件中声明和实现的C++类。我之所以选择这个,是因为由于_GLIBCXX_DEBUG
和预编译库,人们无法轻松地在调试和发布版本之间移动。例如,如果我定义_GLIBCXX_DEBUG
,Boost 将由于源文件中的 ABI 更改而崩溃。
仅标头实现产生了重复符号的问题。例如,在下面的类中,operator==
和非成员swap
将生成乘法定义的符号。
// Foo.hpp
namespace Bar
{
template
class Foo
{
...
};
bool operator==(const Foo& a, const Foo& b) {
..
}
}
namespace std
{
template <>
void swap(Bar::Foo& a, Bar::Foo& b)
{
a.swap(b);
}
}
当声明和实现被拆分时,文件(Foo.hpp 和 Foo.cpp)编译并链接 OK。
让它正确编译和链接的诀窍是什么?
inline bool operator==(const Foo& a, const Foo& b) {
..
}
成员函数是隐式内联的,前提是它们在其类中定义。同样的事情对他们来说也是如此:如果他们可以毫不费力地放入标题中,你确实可以这样做。
由于函数的代码被放入标头中并且可见,因此编译器能够对它们进行内联调用,也就是说,将函数的代码直接放在调用站点(与其说是因为您将内联放在它之前,不如说是因为编译器决定这样做。仅内联是编译器对此的提示)。这可以提高性能,因为编译器现在可以查看参数与函数本地变量匹配的位置,以及参数不会相互别名的位置 - 最后但并非最不重要的一点是,不再需要函数帧分配。
相关文章:
- 使用无符号int作为二进制来在c++中实现一个集
- 为什么我不能使用在 Visual C++ 32 位中实现运算符无符号 int() 作为数组索引的类?
- 是否可以确定函数的参数是否已签名或无符号,以实现可能性超载函数
- 有符号整数和无符号整数C++的实现差异
- 如何从uint8_t的缓冲区读取带符号整数,而不调用未定义或实现定义的行为
- C 实现CNN错误添加符号:命令行中缺少DSO
- 实现内存管理模板类时未解析的外部符号
- 仅使用标头实现的重复符号
- 未解决的外部符号,具有自定义阻塞队列实现
- 高效的无符号到签名转换,避免实现定义的行为
- 高效实现 64 位和 32 位无符号整数之间的双向映射
- 实现自定义非线性最小化,从符号数学到C
- 来自 vtable 的未定义符号是否意味着接口和实现之间存在错误
- 为什么 Vulkan 的 VkBool32 被实现为无符号的 int?
- 在文件中使用仅 C 标头实现时未定义的符号C++
- 我能否在 uint_fast64_t 和无符号长整型之间实现类型等效性
- BigInt实现-将字符串转换为存储为无符号int的二进制表示
- visual如何在c++中实现变音符号
- GLSL截断符号距离表示(TSDF)实现
- 在带有模板的链表实现中无法解析的外部符号