2015-01-03 30 views
4

我不知道如何解釋爲什麼在類模板OuterTempl<T>中創建成員inner是有效的,而在未模糊的類Outer中這樣做是非法的。類模板的嵌套類可以是「不完整的」

// Non-template version 
struct Outer 
{ 
    struct Inner; 
    Inner inner; // incomplete type (I get this) 
}; 

struct Outer::Inner 
{ 
}; 

// Template version 
template<typename T> 
struct OuterTempl 
{ 
    struct InnerTempl; 
    InnerTempl inner; // OK ... Huh!? 
}; 

template<typename T> 
struct OuterTempl<T>::InnerTempl 
{ 
}; 

int main() 
{ 
} 

另請參閱ideone

回答

4

有 - 考慮[temp.mem.class]/1:

甲構件類的類模板的可在其中它被聲明的類 模板定義之外定義。
[注意:成員 類必須在首次使用之前定義,需要實例化(14.7.1)。例如,

template<class T> struct A { 
    class B; 
}; 

A<int>::B* b1; // OK: requires A to be defined but not A::B 

template<class T> class A<T>::B { }; 

A<int>::B b2; // OK: requires A::B to be defined 

- 注完]

同樣重要的是要提到的inner的定義,構成使用Inner上述說明描述,僅實例化一次它是必需的:

除非一個成員已經明確實例化或顯式專門化,否則specializa當要求成員定義存在的上下文中引用的專業化爲 時,會員隱式地實例化成員 ;

由於沒有OuterTempl實例出現在你的代碼,inner的定義從不實例化,以及Inner一個實例是從來沒有必要。因此,這種聲明的嵌套類類型的完整性僅在實例化時需要。這裏您沒有實例化OuterTempl,但是如果您在Inner的定義之前執行,則代碼將會不合格。

也就是說,

template<typename T> 
struct OuterTempl 
{ 
    struct InnerTempl; 
    InnerTempl inner; 
}; 

template struct OuterTempl<int>; // Bad - Ill-formed (NDR?) 

template<typename T> 
struct OuterTempl<T>::InnerTempl {}; 

template struct OuterTempl<int>; // Fine 

Demo

4

定義類時需要定義成員類型。但是,類模板在被實例化之前不會被定義。到那時爲止,任何一種依賴類型都可以改變。只有當類被實例化時才需要定義成員。

另一方面,非模板類的定義是一個定義,它需要知道在那個點上它的成員的大小。