楼主:
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++ 还有它的编译连结特性不存在任何关系。