我正在尝试了解extern模板,但我无法让它工作。我的目标是在单独的编译单元中编译Foo<>
的一些实例,以节省编译时间。在我的代码库中,模板参数是enum class
,所以理论上我能够编译编译单元中的所有实例,并将它们与项目的其余部分链接起来。
以下是我提出的一个小例子:
//Foo.hpp
#pragma once
template <class T>
struct Foo {
Foo();
~Foo();
};
extern template struct Foo<int>;
//Foo.cpp
#include "Foo.hpp"
template struct Foo<int>;
//main.cpp
#include <iostream>
#include "Foo.hpp"
int main(int argc, char **argv) {
Foo<int> foo;
return 0;
}
为了编译,我使用了一个makefile,归结为:
g++ -c ../Foo.cpp ../main.cpp
g++ Foo.o main.o
我使用gcc 7.1.1获得的输出与clang 4.0.1基本相同的是:
main.o: In function `main':
main.cpp:(.text+0x27): undefined reference to `Foo<int>::Foo()'
main.cpp:(.text+0x38): undefined reference to `Foo<int>::~Foo()'
我的主要问题是,为什么Foo<int>::Foo()
和Foo<int>::~Foo()
未编入Foo.o
?
答案 0 :(得分:3)
因为构造函数和析构函数在任何地方都没有定义,所以只能声明它们。您正确地在Foo.cpp
文件中显式实例化模板,但仍未定义函数。
如果您只打算使用Foo<int>
,那么您可以在Foo.cpp
中定义构造函数和析构函数,
template<typename T>
Foo<T>::Foo(){...} // or = default
和
template<typename T>
Foo<T>::~Foo(){...}
并且由于您在Foo.cpp
中显式实例化模板,链接器将找到该定义。否则,您需要在头文件中提供定义。