[英]Nested class declaration: template vs non-template outer class
我有一個c ++模板類,里面有一個嵌套類,如:
template<int d>
class Outer_t
{
public:
class Inner;
Inner i;
};
template<int d>
class Outer_t<d>::Inner
{
public:
float x;
};
int main ()
{
Outer_t<3> o_t; // 3 or any arbitrary int
o_t.i.x = 1.0;
return 0;
}
這編譯沒有任何問題。 但是,只要我聲明一個類似的非模板類,就像這樣:
class Outer_1
{
public:
class Inner;
Inner i;
};
class Outer_1::Inner
{
public:
float x;
};
int main ()
{
Outer_1 o1;
o1.i.x = 1.0;
return 0;
}
我開始收到以下錯誤(我正在使用gcc 4.6.3):“錯誤:字段'我'的類型不完整”。 我知道我可以通過在外部類中定義內聯類內聯來解決這個問題:
class Outer_2
{
public:
class Inner {
public:
float x;
};
Inner i;
};
這將編譯,但我想避免定義嵌套類內聯。 所以我有兩個問題:模板與非模板嵌套類聲明之間存在明顯奇怪差異的原因是什么? 是否有一種優雅的方式來聲明和使用外部類中的nester類,同時避免將其定義為內聯,與模板類的風格大致相同? 在此先感謝您的幫助!
編譯器需要知道成員變量類型的大小才能進行對象布局。 對於Outer_1
,因為Inner
只是一個前向聲明,我們不知道它的大小。 因此編譯錯誤。 但是對於Outer_2
,定義是內聯的,所以當我們到達Inner
類型的成員變量時,我們知道它的大小。
另一方面,類模板在模板實例化發生之前不會被定義。 在您的示例中, 隱式實例化發生在main
。 那時, Inner
的定義是完整的,因此它的大小是已知的。 通過在Inner
的定義之前使用顯式實例化,我們可以看到這種情況。
template<int d>
class Outer_t
{
public:
class Inner;
Inner i;
};
template class Outer_t<3>; // explicit instantation
template<int d>
class Outer_t<d>::Inner
{
public:
float x;
};
int main ()
{
Outer_t<3> o_t; // 3 or any arbitrary int
o_t.i.x = 1.0;
return 0;
}
Clang產生以下錯誤:
a.cc:7:11: error: implicit instantiation of undefined member 'Outer_t<3>::Inner'
Inner i;
^
a.cc:10:16: note: in instantiation of template class 'Outer_t<3>' requested here
template class Outer_t<3>;
^
a.cc:5:11: note: member is declared here
class Inner;
^
如果你想提取嵌套類的定義,我建議的解決方案是讓它像Outer_t
一樣進行模板化,但為方便起見提供別名。
template <typename Dummy = void>
class Outer_1_Impl {
public:
class Inner;
Inner i;
};
template <typename Dummy>
class Outer_1_Impl<Dummy>::Inner {
public:
float x;
};
using Outer_1 = Outer_1_Impl<>;
int main () {
Outer_1 o1;
o1.i.x = 1.0;
}
在定義類時,只能在對象中具有完整定義的非靜態成員。 在你的非模板示例中, Outer_1::Inner
顯然不完整,因為它只是聲明到目前為止。 創建Inner
的成員的唯一方法是確定它就像為Outer_2
所做的Outer_2
。
現在,為什么使用類模板時不會出現問題? 答案是:當你在main()
中實例化Outer_t
時,實際上有一個Outer_t<T>::Inner
可訪問的完整定義! ...並且在使用某種類型T
實例化Outer_t<T>
之前,並不真正需要Outer_t
的定義。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.