在当前的g ++中,我通常包含所有模板化函数,它们将模板参数作为参数,因为必须为每个实例编译它们。
template<typename T>
class A {
public:
void f() { ... }
};
所以在不同的来源中,我会写:
#include <A.hh>
A<int> a1;
a1.f();
A<double> a2;
a2.f();
有时候,当我迫不及想要内联大方法时,我已经手动指定了哪些类将在源文件中使用,但它确实令人讨厌:
template<typename T>
A::A() { ... }
template<typename T>
void A::f() { ... }
A<int>; // manually trigger code generation for int and double
A<double>;
显然,不同的IDE和编译器都有支持这一点的机制。是否有任何标准强制要求,和/或g ++是否支持这样的事情?
答案 0 :(得分:5)
建议的C ++ 0x标准中没有任何内容。事实上,export template
已被删除(无论如何,很少有编译器实现它)。
就内联而言,这完全没有问题。编译器非常聪明,即使它们被标记为inline
并放入头文件中,也不会内联过大的函数。
如果您正在查看从模板中增长的头文件增加的编译时间,请使用预编译的头文件。这些不是标准的,但几乎所有当前的编译器都提供了这样的机制。
答案 1 :(得分:3)
C ++ 0x确实有extern template
,它允许您阻止在编译单元中实例化某些模板。因此,如果您有模板类SomeClass
,则可以将其放在标题中:
extern template SomeClass<int>;
extern template SomeClass<double>;
这将阻止用户实例化模板。在模板的.cpp文件中,您可以使用以下语法强制实例化:
template SomeClass<int>;
template SomeClass<double>;
答案 2 :(得分:3)
我已手动指定将在源文件中使用哪些类,但它确实令人讨厌:
A<int>; // manually trigger code generation for int and double
A<double>;
这不合法(我假设你打算在这里声明虚拟变量,并且错过了他们的名字)。我们将在下面看到为什么
是否有任何标准要求,和/或g ++是否支持这样的事情?
C ++ 03有一个名为export
的东西,但结果证明是错误的。 EDG实现了这一功能,他们使用它的经验表明,实施它并不值得。并且它没有提供有用的功能,单独的编译通常会给你:隐藏你曾经编译过的模板代码。 export
仍然需要模板代码,无论是原始形式还是编码为中级编译器特定语言。见Why we can't afford export。 EDG工作人员David Vandevoorde here给出了一个简短的例子。
对于C ++ 0x和C ++ 0x sans导出,我们有
函数模板,类模板的成员函数或类模板的静态数据成员应在每个隐式实例化的转换单元中定义(14.7.1),除非明确实例化相应的特化(14.7。 2)在一些翻译单位;无需诊断
如图所示,唯一可以实现单独编译的方法是显式实例化您想要单独编译的模板。通过定义虚拟变量,您只需隐式实例化类模板。并且不实例化类模板的成员函数 - 您需要进行虚拟调用或获取其地址。对于所有这些,如果没有在翻译单元中使用隐式实例化的函数,则在优化之后,基于上述引用,它将被实例化,因此不保证不会丢弃隐式实例化的函数。
所以你明确地实例化了类模板,它将通过以下方式显式地实例化其成员函数:
template class A<int>;
template class A<double>;
答案 3 :(得分:1)
即使在当前的C ++标准中,此功能也称为export
。不幸的是,大多数编译器,包括gcc,都不支持它。见http://gcc.gnu.org/bugs/