我如何使用explicit模板实例化用于类定义中定义的模板成员函数
How can I use explicit template instantiation for template member functions defined within a class definition?
为了减少一个大型项目中的编译时间,该项目可以自由地使用模板,我使用" Extern模板"(显式模板实例化(获得了良好的结果,以防止通用模板功能从在许多不同的汇编单元中定义。
然而,关于它的一个令人讨厌的事情是,它不适用于类定义中定义的成员函数。
例如,我有以下模板类:
template <typename T>
struct Foo
{
static T doubleIt(T input)
{
return input * 2;
}
};
现在,我知道FOO最常用于数字类型,因此我将其添加到标题:
extern template struct Foo<int>;
extern template struct Foo<float>;
extern template struct Foo<double>;
和在CPP文件中,添加显式实例:
template struct Foo<int>;
template struct Foo<float>;
template struct Foo<double>;
这不起作用,如OBJ文件上的DumpBin.exe告诉我:
017 00000000 SECT4 notype () External | ?doubleIt@?$Foo@M@@SAMM@Z (public: static float __cdecl Foo<float>::doubleIt(float))
如果我更改我的类定义以定义函数外部类,则可以正确工作:
template <typename T>
struct Foo
{
static T doubleIt(T input);
};
template <typename T>
T Foo::doubleIt(T input)
{
return input * 2;
}
我们可以使用dumpbin验证:
017 00000000 UNDEF notype () External | ?doubleIt@?$Foo@M@@SAMM@Z (public: static float __cdecl Foo<float>::doubleIt(float))
问题使用该解决方案是在类定义之外移动所有函数定义是很多键入的,尤其是当您获得更多模板参数时。
我已经尝试使用dectspec(__ noinline(,但它仍然无法正确外部功能(并在可能的情况下阻止函数的嵌入方式(。
有效的一件事是像这样列举每个功能,但这当然更繁琐:
extern template int Foo<int>::doubleIt(int);
extern template float Foo<float>::doubleIt(float);
extern template double Foo<double>::doubleIt(double);
我想要的是一种将功能定义保持在类定义内部的函数定义的方法,同时仍允许在可能的情况下将函数列入函数,但是当它不嵌入时,仅在其明确的汇编单元中创建它实例化(换句话说,与在类定义外移动功能完全相同的行为(。
您不能双向采用这两种方式,以使编译器需要使用源代码的方法,因为该方法被定义为内联,编译器不会将其编译为如果对象文件未直接在该对象中使用(即使是在任何情况下是在对象中嵌套的,则它都不会以单独的方法存在在对象中(。如果编译器在标题中定义,则始终必须构建函数,以某种方式强迫编译器将该函数的副本存储在对象文件中。
正如指出的那样,您不能同时具有extern
和内线,但是关于额外的打字部分,我做了类似的事情,并试图使用预处理器将其最小化。我不确定您是否会觉得这有用,但是以防万一,我将在其中包含一个模板函数的示例。
文件Foo.h
:
template<typename T1>
struct Foo
{
void bar(T1 input)
{
// ...
}
template<typename T2>
void baz(T1 input1, T2 input2);
};
#include <Foo.inl>
文件Foo.cc
:
template<typename T1>
template<typename T2>
void Foo<T1>::baz(T1 input1, T2 input2)
{
// ...
}
#define __FOO_IMPL
#include <Foo.inl>
#undef __FOO_IMPL
文件Foo.inl
:
#ifdef __FOO_IMPL
#define __FOO_EXTERN
#else
#define __FOO_EXTERN extern
#endif
#define __FOO_BAZ_INST(T1, T2)
__FOO_EXTERN template void Foo<T1>::baz<T2>(T1, T2);
#define __FOO_INST(T1)
__FOO_EXTERN template struct Foo<T1>;
__FOO_BAZ_INST(T1, int)
__FOO_BAZ_INST(T1, float)
__FOO_BAZ_INST(T1, double)
__FOO_INST(int)
__FOO_INST(float)
__FOO_INST(double)
#undef __FOO_INST
#undef __FOO_BAZ_INST
#undef __FOO_EXTERN
因此,它仍然是很多写作,但是至少您不必小心地与不同的模板声明保持同步,也不必明确地浏览所有可能的类型组合。就我而言,我有一个具有两个类型参数的类模板,并带有一个带有额外类型参数的成员函数模板,并且每种都可以占用12种可能的类型。36行比12 3 = 1728更好,尽管我希望预处理程序更喜欢通过每个参数的类型列表以某种方式迭代,但是无法弄清楚如何。
。作为旁注,就我而言,我正在编译一个需要编译所有模板的DLL,因此实际上模板的实例化/声明看起来更像__FOO_EXTERN template __FOO_API ...
。
- 在命名空间中定义函数还是限定函数
- 为什么在定义函数之前先声明它
- 使用用户定义函数的字符串反转
- 用户定义函数中的指针和输入
- 这个c++代码是如何在没有定义函数的情况下运行的
- 具有外部"c"和程序集的未定义函数
- 已定义函数时出现 G++ "未定义的引用"错误
- 将自定义函数传递到基抽象类中以延迟执行
- C++使用 rand 定义函数语法
- Arduino:在 loop() 和自定义函数中运行相同的代码时出现问题
- 将具有固定签名的自定义函数名称注入 CRTP
- 使用定义函数模板别名
- 是否可以使用单个定义定义函数的常量和常规版本?(使用模板,自动,decltype等)
- 在内联程序集中定义函数和从 C++ 调用时出现问题
- 在 Metal 着色器代码中,如何定义函数的 in/out 参数变量?
- 声明和定义函数静态会产生"undefined reference to function_name()"
- 朋友定义函数的名称空间是什么
- 介子 对用户定义函数的未定义引用
- 如何使用 "using" 关键字定义函数原型/签名
- 在 C 结构中定义C++函数