2017-09-26 132 views
0

如果我有一個在.cpp文件而不是.h文件中定義的方法的模板類,我可以使用顯式實例來讓編譯器避免無法解析的外部。模板顯式實例化與前向聲明類型一起工作嗎?

但它會工作,如果顯式實例化是使用前向聲明類型聲明的?

template <typename T> struct Template 
{ 
    void someFunc(); //defined in the .cpp file 
} 

class A; 

template Template<A>; 

想,如果A終於沒有定義,沒有使用Template<A>它的工作?

+0

只是不要分割模板並將其全部定義在頭文件中。 – NathanOliver

+0

沒有使用'A',要求它在這裏完整,所以沒有問題。 – Quentin

+0

@Quentin:謝謝你的回答。如果此代碼是庫的一部分,那麼模板 :: someFunc()符號將在lib中導出,並且在定義A時不會導致未解析的外部錯誤? – Michel

回答

1

首先。編譯器僅在實例化模板時生成代碼(在您的示例中,由於沒有實例化,因此不生成代碼)。其次,你傳遞一個類型模板參數。這裏編譯器將被允許安全地創建一個實例。 在你的例子中,你不會在某處使用這個類型,但是如果你願意,爲了定義一個函數,我的第一句話將再次適用,並且該函數只是在某個地方實例化時生成的。 就在這時,編譯器必須具備所有知識才能生成代碼。

// Example program 
#include <iostream> 


template <typename T> struct Template 
{ 
    void someFunc(); //defined in the .cpp file 
}; 

class A; 
Template<A> foo; 

但是,如果您創建了一個採用非類型參數的模板。如您所擔心的那樣,它會失敗,因爲類型定義不完整。

// Example program 
#include <iostream> 
#include <string> 

class A; 

template <A parm> struct Template 
{ 
    void someFunc() { 
     parm.foo(); 
    } 
}; 

A a; 
using foo = Template<a>; 

這個例子也是一樣的。在這裏,您將創建一個對象a,當然編譯器需要更多地瞭解類型。這就是它失敗的原因。

// Example program 
#include <iostream> 


template <typename T> struct Template 
{ 
    T a; 
}; 

class A; 
Template<A> foo; 

希望這會有所幫助。

+0

我曾經在另一個項目中爲新的類型定義這個模板的專門化時,我有(如預期的)一個未解析的外部函數作爲函數在體內定義。所以在另一個項目中,我有效地使用了這個模板,但是有一個符號在模板定義的時候不存在,並且在創建lib文件之前不會定義。有了這個前瞻性的訣竅,我不再有那個未解決的外部問題,我想知道爲什麼。我相信模板函數的主體必須位於cpp中,以便知道大小。 – Michel