是否有可能为模板化函数的所有模板参数提供一个版本的机器代码?

Poo*_*ria 5 c++ templates function instantiation

这里的一些人告诉它是不可能的,这里的一些人告诉我们可能有一个版本的机器代码用于模板化函数的所有不同模板参数,所以我认为打开关于这个特定事项的线程是有利可图的,如果没有这种可能性,如果存在的话,在什么情况下我们可以依靠它?下面提到的两个主题中都特别考虑了一个例子:

template<size_t num>    
struct Elements{
 public:
  SomeType elements[num];
};

template<size_t num>
void print(const Elements<num> & elements,size_t size){
 //all instances do exactly same thing and with regard to Size that determines the size of object
}
Run Code Online (Sandbox Code Playgroud)

当然还有价值传递版本:

template<size_t num>
void print(const Elements<num> elements,size_t size){
 //all instances do exactly same thing and with regard to Size that determines the size of object
}
Run Code Online (Sandbox Code Playgroud)

Cra*_*rks 5

智能链接器可以识别两个不同的功能体何时相同并将它们组合成一个符号.这在MSVC中称为"COMDAT折叠",在大多数其他地方称为"重复剥离".例如,下面的两个功能可能相同编译PPC上,尽管他们采取不同的类型,因为类型相同的大小,在特定情况下的行为相同.

template<typename T>
GetLowBit( T foo ) { return T & 1; }

GetLowBit<unsigned long>(ulong x); // compiles to "li r4, 1 ; and r3, r3, r4 ; blr "
GetLowBit<signed long>(long x); // also compiles to "li r4, 1 ; and r3, r3, r4 ; blr "
Run Code Online (Sandbox Code Playgroud)

所以链接器可以使它们的"名称"指向同一个地方,因此调用会GetLowBit<unsigned long>转到与调用相同的地址GetLowBit<signed long>.因此,通常,可以将函数的不同模板实例折叠在一起,所有函数都以相同的方式在相同的类型大小上操作.(特别是,存储指针或枚举的容器往往会折叠在一起.)

这不仅适用于模板功能.一些链接器可以注意到任何两个函数具有相同的主体,并合并它们.特别是我看到MSVC倾向于崩溃每个虚函数,它只会返回一个超级函数,例如

class A
{ 
  virtual void nothing() {};
}

class B
{
   virtual void empty() {};
}
Run Code Online (Sandbox Code Playgroud)

我经常看到(在反汇编程序中调试其他东西时)vtable条目nothingempty两者都指向同一个函数体,而这又是一个函数体ret.

你能指望这个吗?不可以.这是智能链接器在注意到它们时可能提供的功能.你的链接器可能很愚蠢 - 那里有很多糟糕的编译器.只有在提供某些命令参数时才会发生这种情况.某些功能可能会发生,但只有链接器知道的原因才会发生.它甚至可能因构建而异,具体取决于程序中的其他内容.

所以一般来说,是的,这可能会发生,当它发生时,它可以节省可执行的大小.但除非您非常熟悉链接器及其所有功能,否则您无法指望它发生.