可变参数模板在目标文件中有重复的符号?

Posted

技术标签:

【中文标题】可变参数模板在目标文件中有重复的符号?【英文标题】:Variadic templates have duplicate symbols in object files? 【发布时间】:2018-06-29 13:26:53 【问题描述】:

我有以下测试程序:

#include <cstdio>

template<int i, int j, int k>
struct Dispatcher 
  template<typename... F>
  static inline void call1(bool a, bool b, int* output, F...) 
    *output = i;
    if (a) *output += j;
    if (b) *output += k;
  

  template<typename F>
  static inline void call2(bool a, bool b, int* output, F) 
    *output = i;
    if (a) *output += j;
    if (b) *output += k;
  
;


int main() 
  int output;
  Dispatcher<1, 2, 3>::call1(true, false, &output, 1337);
  printf("%i\n", output);
  Dispatcher<1, 2, 3>::call2(true, false, &output, 1337);
  printf("%i\n", output);
  return 0;

程序按预期构建和运行,但“nm -C”显示它包含以下符号:

000000000040065a W void Dispatcher<1, 2, 3>::call1<int>(bool, bool, int*, int)
000000000040065a W void Dispatcher<1, 2, 3>::call1<int>(bool, bool, int*, int)
00000000004006a4 W void Dispatcher<1, 2, 3>::call2<int>(bool, bool, int*, int)

没有拆解,它们是:

000000000040065a W _ZN10DispatcherILi1ELi2ELi3EE5call1IIiEEEvbbPiDpT_
000000000040065a W _ZN10DispatcherILi1ELi2ELi3EE5call1IJiEEEvbbPiDpT_
00000000004006a4 W _ZN10DispatcherILi1ELi2ELi3EE5call2IiEEvbbPiT_

为什么函数“call1”出现两次,而“call2”只出现一次?看起来它与可变参数模板参数有关......

我正在使用带有“-std=c++11 -O0”标志的 gcc 版本 4.8.5 进行构建。 (即使在我的真实代码中使用 -03,我也会遇到问题,但测试程序会在没有 -O0 的情况下内联。)

【问题讨论】:

没有 gcc8 和 clang6 的复制,所以看起来你过时的编译器有问题。 感谢您的浏览!我也无法使用 clang 3.7.1 进行复制。我想知道,这是旧编译器的外观问题,还是真的复制了整个函数? 老实说,我不确定;这比我通常的专业领域低。无论如何,除非二进制大小有问题,否则这是否重要? 可以使用objdump检查函数是否重复objdump -S a.out | c++filt -n。我也无法重现该问题。 链接后他们不会被抛弃吗? 【参考方案1】:

@BaummitAugen 和 @PaoloCrosetto 为我指明了正确的方向 - 这显然是一个仅限于旧版本 gcc 的问题,它似乎并没有实际增加编译后的可执行文件的大小。

【讨论】:

以上是关于可变参数模板在目标文件中有重复的符号?的主要内容,如果未能解决你的问题,请参考以下文章

中继可变参数模板参数时出现 Visual Studio 错误 [重复]

重复的可变参数模板参数

可变参数模板对

使用可变参数模板进行扩展[重复]

C++11 可变参数模板

使用模板化可变参数模板参数作为专用参数