我想创建一个只接受一些特定类型参数的模板类(我们称之为Foo
)(仅假设double
和float
)。通常模板在头文件(.h
)中实现,因为它不知道如何在用户代码中实例化。在这种情况下,在实现文件(.cpp
)中实现类更有意义,如下所示:
// Foo.cpp:
template <class T>
class Foo
{
// Insert members here
};
typedef Foo<double> Foo_d;
typedef Foo<float> Foo_f;
这将在编译Foo.cpp时实例化并编译该类。但是,如何在头文件中声明这一点而不为Foo_d
和Foo_f
编写单独的声明?
答案 0 :(得分:5)
除非我弄错了,否则您所描述的内容正是新C ++ 11 extern template
功能的用例。要使用此功能,您可以将模板类的接口放在头文件中。然后,您将使用以下行结束头文件:
extern template class Foo<float>;
extern template class Foo<double>;
这告诉任何包含头文件的文件在使用时不要尝试实例化模板。然后,在您的C ++文件中,您将实现模板类,然后以行
结束template class Foo<float>;
template class Foo<double>;
最后两行强制编译器在此转换单元中实例化模板,因此不会出现任何链接器错误。
希望这有帮助!
答案 1 :(得分:5)
您可以在头文件中定义模板,声明方法,但不定义它们。例如:
template <typename T>
class Foo {
T val;
public:
Foo (T t);
T value ();
};
typedef Foo<double> Foo_d;
typedef Foo<float> Foo_f;
在.cpp
文件中,您完成方法的实现,然后实例化您想要的模板。
#include "foo_template.hpp"
template <typename T>
Foo<T>::Foo (T t) : val(t) {}
template <typename T>
T Foo<T>::value () { return val; }
template class Foo<double>;
template class Foo<float>;
目标文件应具有来自模板Foo_d
的显式实例化的Foo_f
和Foo
的实例化。用于模板Foo
的任何其他类型都将导致链接错误,因为它们的实例化将不存在。或者,更迂腐地,编译器像往常一样按需创建实例化,但是它将无法解析与类的方法相对应的符号,因为这些符号的显式实例化将不存在。