when instantiating a template, the compiler creates a new class with the given template argument.
当初始化一个模板时,编译器会用给定的参数建立一个新的类
For example
比如:
template<typename T>
struct Foo
{
T bar;
void doSomething(T param) {/* do stuff using T */}
};
// somewhere in a .cpp
Foo<int> f;
When reading this line, the compiler will create a new class (let’s call it FooInt), which is equivalent to the following:
当编译到这行时,编译器将创建一个新类(这里权且称为FooInt),它与以下代码等价:
struct FooInt
{
int bar;
void doSomething(int param) {/* do stuff using int */}
}
Consequently, the compiler needs to have access to the implementation of the methods, to instantiate them with the template argument (in this case int). If these implementations were not in the header, they wouldn’t be accessible, and therefore the compiler wouldn’t be able to instantiate the template.
因此,编译器需要扫描所有方法的实现,以便能够用模板参数(这里是int)实例化这些类。如果这些实例不在头文件中,他们将无法被访问,因此编译器也无法实例化模板。
A common solution to this is to write the template declaration in a header file, then implement the class in an implementation file (for example .tpp), and include this implementation file at the end of the header.
这个问题的通用解决方法是在头文件中进行模板声明,然后在实例文件中实例化这个类(比如 .tpp),并且将这个实例文件包含在头文件的末尾。
// Foo.h
template <typename T>
struct Foo
{
void doSomething(T param);
};
#include "Foo.tpp"
// Foo.tpp
template <typename T>
void Foo<T>::doSomething(T param)
{
//implementation
}
This way, implementation is still separated from declaration, but is accessible to the compiler.
这样一来,实现依然与声明相分离,并且可以编译了。
Another solution is to keep the implementation separated, and explicitly instantiate all the template instances you’ll need:
另一种解决方案是,保持实现分离,并且明确支持所需要的所有模板实例:
// Foo.h
// no implementation
template <typename T> struct Foo { ... };
//----------------------------------------
// Foo.cpp
// implementation of Foo's methods
// explicit instantiations
template class Foo<int>;
template class Foo<float>;