我使用以下模式将模板声明和实现分开:
template <typename T>
struct Foo
{
void DoIt();
}
template <typename T>
void Foo<T>::DoIt() { // impl code
};
template class Foo<int>;
template class Foo<float>;
现在我想为Foo添加一个新方法,但是impl.cpp文件已经很大了,所以我想把它移到另一个文件impl2.cpp;
template <typename T>
struct Foo
{
void DoIt();
void RemoveIt();
}
template <typename T>
void Foo<T>::DoIt() { // impl code
};
template class Foo<int>;
template class Foo<float>;
template <typename T>
void Foo<T>::RemoveIt() { // impl code
};
template class Foo<int>;
template class Foo<float>;
这里主要关注的是重复的实例化,我该如何避免这些?
答案 0 :(得分:1)
您需要将常规模板参数T
的实现包含在标头中,并在源文件中包含int
和float
的显式实例化。
// decl.h
template <typename T>
struct Foo
{
void DoIt();
void RemoveIt();
}
#include "impl1.ipp"
#include "impl2.ipp"
// impl1.ipp
template <typename T>
void Foo<T>::DoIt() { // impl code
};
// impl2.ipp
template <typename T>
void Foo<T>::RemoveIt() { // impl code
};
// inst.cpp
#include "decl.h"
template class Foo<int>; // explicit instantiation goes in source file
template class Foo<float>; // explicit instantiation goes in source file
// main.cpp
#include "decl.h"
int main()
{
// call with concrete template arguments
Foo<int>::DoIt();
Foo<float>::RemoveIt();
}
为什么呢?因为DoIt
和RemoveIt
是函数模板,而不是函数,并且在看到传递给它们的模板T
之前无法编译它们。因此Foo
的所有客户端不仅需要包含您的标头,还需要包含您的实施文件。最方便的方法是让标题包含实现。这就是我将它们重命名为.ipp
的原因。
答案 1 :(得分:1)
请执行以下操作:
Foo<T>::DoIt()
的定义移至名为的某个头文件
ImplDoIt.h(不一定与decl.h在同一目录中)Foo<T>::RemoveIt()
相同 - ImplRemoveIt.h