作者:
Keitaro (動き出す時間...)
2025-04-09 22:46:27開發平台(Platform): (Ex: Win10, Linux, ...)
Win10
編譯器(Ex: GCC, clang, VC++...)+目標環境(跟開發平台不同的話需列出)
MSVC
問題(Question):
請教template function在dll裡面兩種實作
補充說明(Supplement):
眾所周知 template function實體化T有兩種方式
1. 直接把template function寫在header
2. template function寫在cpp, 需要另外宣告T實體化
今天假設template寫在一個dll裡面
而我有另外一隻程式MyApp需要用這個dll
在上述兩種實體化template狀況 產生兩種不同的結果
以下是我跟chatgpt討論的結果 想跟板上各位先進請教是否哪裡有錯
1. 當template function實作完全寫在header裡面
則MyApp在include這個dll header時 T實體化
template程式碼完全被展開後直接編譯 然後變成MyApp的一部分
此時dll template header 相當於"直接變成MyApp的header"
由於編譯出來的程式碼直接變成MyApp的一部分
如果用debug設定template function中斷點
會看到stack顯示 MyApp::func() 而非 dll::func() (示意)
2. template function寫在cpp裡面
因為需要額外做實體化宣告T 產生了一個問題
如果MyApp使用template需要的T type 沒有在dll裡面宣告實體化 則compile會報錯
ex: dll裡面只有明確宣告T為int 但是MyApp使用template時希望T為float
因此這種方式需要確保MyApp使用template所需求T 已經明確在dll裡面被實體化宣告
這種狀況跟一般function沒有差別 template function是存在在dll裡面
debug設定中斷點就會看到dll::func()
兩者差異
A. template function在1的狀況下是在MyApp裡面, 而2是在dll裡面
B. 假設要修改function 則1的狀況:
dll重build後更新dll檔給MyApp執行測試 -> 沒用
dll重build後把lib檔給MyApp重新link -> 沒用
原因在於 因為header已經變成MyApp的一部分
所以要"直接修改MyApp include的dll header" 而非 "dll project底下的header"
除非MyApp include path直接指向dll project的目錄讓上述兩者是同一個檔案
但一般來說不會這樣做 不同project會分不同目錄
dll會經過正常release build後打包header/lib/dll再給其他project使用
由於這種狀況header相當於直接變成MyApp的 因此要debug測試
直接修改include path裡面的header即可 跟dll project本身完全無關
至於2當然就沒甚麼好說的 dll重build後更新給MyApp重測即可
C. Code size
1的狀況 template function是直接跟MyApp包在一起的
因此如果dll本身也有其他地方用到template function
則會變成MyApp跟dll兩邊都有template function的情況
至於2當然就沒啥好說的
chatgpt告訴我 STL lib就是採用把template class function全部寫在header的作法
因為STL開發者不可能知道使用者會用vector/list/map去包甚麼東西
所以根本不可能採用第二種方式"事先"宣告template實體化(更何況user也可能自訂型別)
以上 如果有錯的話還請版上各位指教 感謝
作者:
LPH66 (-6.2598534e+18f)
2025-04-10 03:55:00概念上應該還行, 然後這裡有個和 1. 相關用語「僅檔頭庫」(header-only library) 這是模版函式庫的常用實作方式如你所說, 由於僅有檔頭所以跟 dll/lib 這種預編函式庫基本上就沒什麼關係了那這裡可能就有個 XY 問題了: 因為 C++ 這個機制的關係這篇文章的大前提「dll 中的模版」其實是個很奇怪的需求我會想問為什麼會有把模版編進 dll 的需求?
作者:
Keitaro (動き出す時間...)
2025-04-10 08:10:00感謝樓上回覆 我也是看到同事寫template class放在一個dll project其中一個header裡面 要debug都沒辦法設中斷點去查資料才了解template的實作竟有這樣的差異如您所說 這個template class其實已經跟這個project的屬性是dll/lib/exe完全無關了 也不知道寫code的前同事是否考慮過這問題:)補充 chatgpt告訴我 c++20新增的module概念 可以支援把template class/function放在dll cpp裡面了
作者:
wulouise (在線上!=在電腦前)
2025-04-10 21:39:00header only lib怎麼會有dll?dll裡面只有translation unit吧,難道我那邊理解錯誤
作者:
tinlans ( )
2025-04-12 20:23:00在過去,template 的資訊在編譯後就完全消失了,這帶來了很多不便,後來做 LTO 時各家編譯器開始設法保存原始碼的資訊到編譯後的產物裡,這也是為什麼你會問到 modules可以這樣的原因,但它本質上其實並沒有多少改變。另外你的用語是有問題的,template 應該放在後面,兩個名詞放在一起時是名詞修飾名詞,後面的名詞才是主體。class template、function template 這樣寫才對。至於為什麼要強調這個?因為 template 在 C++ 就是一種還沒有實體的骨架這樣的東西,需要被實體化。你顛倒過來寫,如果不是英語不好,那就是基礎概念理解上存在嚴重的誤區。「相當於直接變成MyApp的header」這描述也很奇怪,header的從屬性是跟著 project 走,所以你其它地方描述倒是沒啥問題,只是 header 寫出來就是給人家 include 的,只要include 了就是用到了它,但從屬關係並不會因此改變。不過這裡講的 header 從屬性是更抽象的概念,和 C++ 還有它的編譯連結特性不存在任何關係。