了解c ++中的extern模板

时间:2017-07-26 22:01:27

标签: c++ c++11 templates

我正在尝试了解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

1 个答案:

答案 0 :(得分:3)

因为构造函数和析构函数在任何地方都没有定义,所以只能声明它们。您正确地在Foo.cpp文件中显式实例化模板,但仍未定义函数。

如果您只打算使用Foo<int>,那么您可以在Foo.cpp中定义构造函数和析构函数,

template<typename T>
Foo<T>::Foo(){...} // or = default

template<typename T>
Foo<T>::~Foo(){...}

并且由于您在Foo.cpp中显式实例化模板,链接器将找到该定义。否则,您需要在头文件中提供定义。