alv*_*ion 8 c++ templates inline
为了减少大量项目中自由使用模板的编译时间,我使用"extern模板"(显式模板实例化)来防止在许多不同的编译单元中定义公共模板函数.
但是,有一件令人讨厌的事情是它不适用于类定义中定义的成员函数.
例如,我有以下模板类:
template <typename T>
struct Foo
{
static T doubleIt(T input)
{
return input * 2;
}
};
Run Code Online (Sandbox Code Playgroud)
现在,我知道Foo最常用于数字类型,所以我将它添加到标题:
extern template struct Foo<int>;
extern template struct Foo<float>;
extern template struct Foo<double>;
Run Code Online (Sandbox Code Playgroud)
在cpp文件中,添加显式实例化:
template struct Foo<int>;
template struct Foo<float>;
template struct Foo<double>;
Run Code Online (Sandbox Code Playgroud)
这不起作用,因为obj文件上的dumpbin.exe告诉我:
017 00000000 SECT4 notype () External | ?doubleIt@?$Foo@M@@SAMM@Z (public: static float __cdecl Foo<float>::doubleIt(float))
Run Code Online (Sandbox Code Playgroud)
如果我改变我的类定义来定义类头之外的函数,那么它可以正常工作:
template <typename T>
struct Foo
{
static T doubleIt(T input);
};
template <typename T>
T Foo::doubleIt(T input)
{
return input * 2;
}
Run Code Online (Sandbox Code Playgroud)
我们可以使用dumpbin验证:
017 00000000 UNDEF notype () External | ?doubleIt@?$Foo@M@@SAMM@Z (public: static float __cdecl Foo<float>::doubleIt(float))
Run Code Online (Sandbox Code Playgroud)
该解决方案的问题在于,在类定义之外移动所有函数定义需要大量输入,尤其是当您获得更多模板参数时.
我已经尝试过使用declspec(__ noinline),但它仍然没有正确地对函数进行外设(并且在可能的情况下阻止函数的内联是不合需要的).
有一件事是单独枚举每个函数,就像这样,但这当然更麻烦:
extern template int Foo<int>::doubleIt(int);
extern template float Foo<float>::doubleIt(float);
extern template double Foo<double>::doubleIt(double);
Run Code Online (Sandbox Code Playgroud)
我想要的是一种将函数定义保留在类定义中的方法,同时仍允许在可能的情况下内联函数,但是当它没有内联时,只在编译单元中创建它,在那里显式实例化(在换句话说,与在类定义之外移动函数完全相同的行为).
你不能同时拥有这两种方法,为了内联该方法,编译器需要使用源代码,因为该方法是内联定义的,如果不直接使用它,编译器不会将其编译到目标文件中该对象(即使它是内联的,在所有情况下它也不会作为单独的方法出现在对象中)。如果函数在标头中定义,编译器将始终必须构建该函数,以某种方式强制编译器在目标文件中存储该函数的副本不会提高性能。