2017-11-25 243 views
0

假设我有一个设计好的头文件,其中包含一个模板类和两个包含完全相同的模板类实例的源文件以及一个重复函数。这是...模板实例化 - 编译器如何避免重复符号?

做作头(thing.hpp):

#pragma once 

template <typename T> 
class Thing { 
    public: 
    T t; 
    public: 
    T& value() { 
     return t; 
    } 
}; 

thing.cpp:

#include <thing.hpp> 

template class Thing<int>; 

int MeaningOfLife() { 
    return 42; 
} 

thingy.cpp:(完全一样thing.cpp)

编译和链接后(在OS X上使用clang),似乎只有MeaningOfLife被视为重复符号,但模板实例化的符号(它只是Thing::value())不是。在仔细检查拆卸后,似乎在Thing::value()的符号上放置了组装指令。

问题0:暗示此指令正在做一些事情来防止符号被多次定义,但是它究竟在做什么?

问题1:其他编译器可能在其他地方(例如,Linux,Windows等)如何做到这一点?

问题2:如果我反复地改变了其中一个重复模板实例的汇编代码会怎么样?也就是说,相同的符号,不同的功能体。智能编译器会检测出差异吗?

回答

1

粗略谷歌搜索使我们these OSX docs,其中规定:

.weak_definition指令导致symbol_name是弱定义。 symbol_name只能在coalesced部分中定义。 C++编译器使用它来支持模板实例化。 [...]

它接着以限定coalesced从而:

coalesced部可以包含任何指令或数据,并且当一个符号的一个以上的定义可在多个被定义用于目标文件被链接在一起。静态链接编辑器保留与链接的第一个对象文件中的合并符号相关联的数据,并以静默方式丢弃来自其他对象文件的数据。 coalesced部分的一个示例是编译器为C++模板的隐式实例生成代码。

我不知道会发生什么,如果你修改了这些定义(我还没有尝试过)之一,但该文档意味着链接只是一味地需要找到第一个哪一个。

+0

我以前见过这个,但是这看起来像是OS X的特定情况。我想知道其他系统可以做什么。 –

+0

@MonatheMonad其他系统会做类似的事情。语言规范允许多种模板类型的定义。它们都应该匹配,但是如果它们不是编译器(链接器)将首先发现并且不需要发布诊断。 – 1201ProgramAlarm