2017-09-05 78 views
2

將只聲明但未定義的類的標識符用作模板參數和模板特化是有效的。是一個沒有定義作爲模板參數有效的類聲明

類似的東西:

template<typename T> 
class NodeInfo; 

template<typename T> 
class GraphInfo; 

template<typename T> 
class Graph { 
public: 
    GraphInfo<T> graphInfo; 
    NodeInfo<T> nodeInfo; 
}; 


// specialisation 
class ContextInfo; 

template <> 
class NodeInfo<ContextInfo> { 
public: 
    int a, b, c; 

}; 

template <> 
class GraphInfo<ContextInfo> { 
public: 
    int a, b, c; 
}; 



int main() { 
    Graph<ContextInfo> g; 
} 

編譯沒有沒有GCC 7的任何警告,但我不知道這是否是做有效的事還是我創造某種與未定義行爲?

+2

這是完全有效的。現在,如果模板嘗試使用其參數進行某些操作,那需要一個定義的類,那麼最終會出現編譯失敗,但只有在實例化模板時纔會出現。 –

+0

除了完全有效之外,它也非常有用。您可以使用簡單的標籤來指定一個域。例如'座標'和'座標'。該標籤使這些類型不同,並且您不能錯誤地將其分配給另一個(造成圖形代碼中令人討厭的錯誤)。 – StoryTeller

+1

您的代碼不訪問任何類的任何成員,也不會調用任何成員函數。因此編譯器不需要知道你聲明的類的定義。做一些需要知道類定義的東西(例如訪問成員或調用成員函數),並且代碼不會被編譯。 – Peter

回答

3

這是fine in principle

[注:模板類型參數可能是一個不完整的類型(6.9)。 - 注完]

然而,不完整的類類型may not be used with the standard library,除非另有規定:

[的]影響在下列情況下,不確定的:[...]
- 如果一個不完全類型(6.9)在實例化模板組件時用作模板參數,除非該組件特別允許使用。

例如:

模板參數的declvalT可以是一個不完整的類型。

由於C++ 17,更多的圖書館設施允許使用不完整的類型; for example vector

一個不完整的類型T可實例化vector時如果分配器滿足分配器完整性 要求被使用。 T必須在引用 向量的最終專業化的任何成員之前完成。

+0

我不太確定std部分。我知道我不能使用'std :: vector '這很明顯。但'std :: vector > list'應該是有效的,因爲'ContextInfo'僅用於這裏的專業化,'Graph '本身是完整的,那是對的嗎? –

+0

@ t.niese是的,這是正確的。實際上,從C++ 17開始,你可以將'std :: vector '寫爲例如一個類成員,只要你在使用任何成員函數(包括析構函數 - 因此你需要給父類定義一個用戶定義的析構函數)之前定義'ContextInfo'。 – ecatmur

1

是的,它很好。一個不完整的類型被允許用作template argument

對於類型模板參數模板參數必須是類型-ID,其可命名一個不完整的類型

+0

請注意,在'std'中使用不完整類型的UB是最常見的類型,請參閱[why-c-containers-dont-allow-incomplete-types](https://stackoverflow.com/questions/18672135/why -c的容器 - 不要 - 允許不完全類型)。 – Jarod42

相關問題