我知道变量/对象有内部和外部链接,但我不知道“类型”也有内部和外部链接。当我用 GCC 编译代码时,出现了以下警告:
'ShaderModuleObject' 有一个字段 'GFXAPIShaderModuleHandle ShaderModuleObject::handle',其类型具有内部链接 [-Wsubobject-linkage]
这是代码,我将其粘贴到 Godbolt 中,但我没有看到相同的警告,或者即使 Godbolt 启用了警告:
#define GFX_API_NULL_HANDLE 0
template <typename T, void(*deleter)(T)>
struct MoveOnlyGFXAPIHandle
{
MoveOnlyGFXAPIHandle() : handle(GFX_API_NULL_HANDLE) {}
MoveOnlyGFXAPIHandle(T handle) : handle(handle) {}
MoveOnlyGFXAPIHandle(const MoveOnlyGFXAPIHandle&) = delete;
MoveOnlyGFXAPIHandle(MoveOnlyGFXAPIHandle&& other) : handle(other.handle) { other.handle = GFX_API_NULL_HANDLE; };
MoveOnlyGFXAPIHandle& operator=(const MoveOnlyGFXAPIHandle&) = delete;
MoveOnlyGFXAPIHandle& operator=(MoveOnlyGFXAPIHandle&& other)
{
this->reset();
handle = other.handle;
other.handle = GFX_API_NULL_HANDLE;
return *this;
}
void reset() {
if (handle != GFX_API_NULL_HANDLE)
{
deleter(this->handle);
handle = GFX_API_NULL_HANDLE;
}
}
void assign(T handle) { reset(); this->handle = handle; }
operator T() const { return handle; }
T get() const { return handle; }
~MoveOnlyGFXAPIHandle() {
reset(); }
private:
T handle;
};
using GFXAPIShaderModuleHandle = MoveOnlyGFXAPIHandle < int,
+[](int handle) {
//destroyShaderModule(handle);
} > ;
struct ShaderModuleObject {
GFXAPIShaderModuleHandle handle;
};
int main()
{
ShaderModuleObject module_object;
return 0;
}
什么是具有内部和外部链接的类型?为什么我的类型具有内部链接?为什么这是一件坏事,以至于 GCC 会发出警告?
这是 MCVE:
这是怎么回事?别名为 的类型
Bar
具有内部链接,因为它只能通过名称从当前翻译单元引用。发生这种情况是因为它使用了 lambda(顺便说一下,它是匿名的,根本无法通过名称引用,因此没有链接),并且将其包含header.h
在不同的翻译单元中会导致生成不同的类型,并违反 ODRFrob
。这个例子本身没什么问题(因为只有一个翻译单元),但在更复杂的场景中,这可能会导致奇怪的错误和混乱的错误消息。例如,如果
Bar
用作 DLL 接口的一部分,则损坏的符号名称可能会有所不同,具体取决于包含头文件的翻译单元,从而产生神秘的链接器错误:另一个 MCVE 中,此类问题会导致 HARD 错误而不是警告: