我发现自己对模板的理解存在挑战,我知道模板的源代码必须放在头文件中才能访问模板实例化的所有依赖类型。
所以,在这个例子中:
// This code cannot be placed in the cpp file
template <typename T> T foo(T v)
{
return -v;
}
的主体T foo(T v)
必须放在头文件中,然后,当foo
函数在某处实例化时,会创建“真实”主体函数,T
用真实类型替换符号。使用此代码:
int bar = 5;
float baz = 6.66f;
bar = foo<int>(bar);
baz = foo<float>(baz);
模板实例化机制基于之前定义的模板创建以下函数:
int foo(int v)
{
return -v;
}
float foo(float v)
{
return -v;
}
但是,当我们有一个模板类时,该类可以具有根本不使用依赖类型的函数:
template <typename T> class Foo
{
Foo() : mistery(0), value(0) {}; // We're using the dependant type.
AddMistery() { ++mistery; }; // We are not using the dependant type.
int mistery;
T value;
};
我首先想到该AddMistery
方法可以放在cpp文件中,因为该方法没有使用依赖类型,但是当我尝试时,链接失败。这会儿我一记耳光,想起模板类的不同实例不是同一个类。因此,当链接器完成它的工作时,它会查找AddMistery
方法的主体,但没有找到它,因为 ir 被放入 cpp 文件中:
// Foo.h
template <typename T> class Foo
{
Foo() : mistery(0), value(0) {}; // We're using the dependant type.
AddMistery(); // We are not using the dependant type.
int mistery;
T value;
};
// Foo.cpp
#include "Foo.h"
template <typename T> Foo<T>::AddMistery()
{
++mistery;
}
// Main.cpp
#include "Foo.h"
int main(int argc, char **argv)
{
Foo<int> i;
Foo<float> f;
i.AddMistery(); // Link Error, where's the Foo<int>::AddMistery body?
f.AddMistery(); // Link Error, where's the Foo<float>::AddMistery body?
return 0;
};
所以,最后,这是一个问题:有一种方法可以在头文件和 cpp 文件之间拆分模板类,将所有非类型相关方法的主体移动到 cpp,而不是将所有方法主体保留在头文件中?