2017-07-26 61 views
0

我想了解extern模板,但我不能得到它的工作。我的目標是編譯一些instanciations,如果Foo<>在一個單獨的編譯單元中,以節省編譯時間。在我的代碼庫中,模板參數是enum class,所以理論上我可以編譯編譯單元中的所有實例並將它們與項目的其餘部分相鏈接。瞭解extern模板在c + +

這裏是一個小例子,我想出了:

//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,基本上鏗鏘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

因爲你沒有提供任何編譯器讓它知道構造函數和析構函數做什麼。他們添加兩個數字嗎?減去兩個數字?計算「戰爭與和平」中的單詞數量?計算引腳頂端的天使數量?您必須在某處編寫構造函數,以便編譯器實例化它。 –

回答

3

因爲構造函數和析構函數都不是,所以在任何地方都定義了,你只能聲明它們。您正確顯式實例化Foo.cpp文件中的模板,但函數仍未定義。

如果你只打算使用Foo<int>,那麼你可以定義Foo.cpp構造函數和析構函數,

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

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

,並由於您明確實例化模板在Foo.cpp中,鏈接器將找到該定義。否則,您需要在頭文件中提供定義。

+0

明白了。我忽略它,因爲我專注於外部模板。謝謝。 – OutOfBound

+0

@OutOfBound另請參閱https://stackoverflow.com/q/8130602/3093378以獲取有關'extern模板'的真實用法的更多詳細信息。 – vsoftco

+0

我不能說這個例子中代碼的意圖是爲了演示'Foo '還是'Foo '的模板函數定義。對於前者,在兩個'::'s之前加'';對於後者,你需要'template <> Foo :: Foo(){...}'和類似的析構函數。 –