2017-11-25 200 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