【发布时间】:2015-04-03 02:08:07
【问题描述】:
我有一个简单的可变参数模板代码来将参数写入流:
#include <iostream>
void tostream(std::ostream& os) {
}
template<typename T, typename... Args>
void tostream(std::ostream& os, const T& v, const Args&... args) {
os << v;
tostream(os, args...);
}
template<typename... Args>
void log(std::ostream& os, const Args&... args) {
tostream(os, args...);
}
我可以打电话给:
log(std::cout, "Hello", 3);
log(std::cout, "Goodbye", 4);
我使用 Visual Studio 2013 编译此代码,并在(发布配置)上进行所有优化,并使用 IDA Disassembler 打开生成的可执行文件。
我看到的是编译器实例化了log() 函数的两个副本。一种采用const char[6], int,另一种采用const char[8], int。
当单步执行这些函数并观察调用堆栈窗口时,这在调试器中也很明显。
除了签名之外,这两个函数是相同的。
有没有办法让编译器相信这两个函数实际上应该是一个接受const char*, int 而不是两个函数的函数?
这对我来说是个问题,因为我有数百个这样的函数实例使我的可执行文件膨胀,其中大部分是可以避免的。
对于不同的参数组合,该函数仍然会有很多实例化,但它们会少很多,因为我只有很少的可能的参数组合。
可以解决这个问题的方法是像这样调用函数:
log(cout, (const char*)"Hello", 3);
log(cout, (const char*)"Goodbye", 4);
但这是不可接受的,因为它会使代码非常混乱。
【问题讨论】:
-
不是一个真正的答案,但您是否尝试暗示编译器它可能想要
inline函数调用?或者甚至强迫它? -
你已经在这里六年,但你还在为所有的标题写标签吗? :sadface:
-
@shoosh:你有没有发现几乎没有其他人这样做,并且当他们这样做时,标题会被编辑?我们已经有一个标签系统,与您的标题前缀不同,它是语义和索引的。
-
@LightningRacisinObrit 我很乐意,以防这实际上是全球强制的风格指南,而不仅仅是您的个人喜好。
-
Should questions include tags in titles? -- 对于 comdat,递归通过限制可能会限制清除重复函数的能力。在第一次通过时,
<<被弃牌。在第二次通过时,tostream被弃牌。log我猜如果你添加另一个 comdat 折叠通行证会被淘汰?
标签: c++ templates variadic-templates