在使用模板时,一般要求定义与实现在一起,那么为了程序的统一与美观,若想在仅在头文件中定义,在源文件中实现,例如:
// template.h
#include
template <typename T>
struct TemplateTest {
T value;
void func();
};
// template.cc
template <typename T>
void TemplateTest<T>::func() {
std::cout << typeid(T).name() << std::endl;
}
// test_template.cc
#include "template.h"
int main() {
TemplateTest<int> test;
test.func();
return 0;
}
啊欧,就会报错
/tmp/ccPghOjU.o: In function `main':
test_template.cc:(.text+0x1f): undefined reference to `TemplateTest<int>::func()'
collect2: error: ld returned 1 exit status
报错提示没有实现这个函数。 这个问题导致我改了项目中代码的实现方法。
为什么把定义放在源文件中,编译就失败了呢,因为每个源文件的编译都是独立的,尽管在test_template.cc进行了TemplateTesttest的使用,但是在template.cc中却感知不到,所以也就没法定义相关的实现。
只需要让template.cc中感知到T有int类型的情况,那编译应该就没问题。这里有个语法,叫模板实例化,像这样:
template struct TemplateTest<int>;
把这行代码放在template.cc中:
// template.cc
#include "template.h"
template <typename T>
void TemplateTest<T>::func() {
std::cout << typeid(T).name() << std::endl;
}
template struct TemplateTest<int>;
整个代码的编译就没得问题了,通过这种方式即可以实现模板函数声明与实现的分离。
但是这样做,又是否违背了模板设计的初衷呢?每次不同类型的调用,还得自己去增加实例化,看起来还是不太舒服。