基於@Igor的評論,我已經找到了一些針對這個問題的解決方法。基於參考Bar
在其聲明內的事實是指Bar
(引用@Igor)。
請注意,所有這些解決方法都依賴於baz
可以聲明爲指針這一事實。 baz
不是一個指針導致這是在評論中提到的@Nir並導致該錯誤的遞歸問題:
field has incomplete type 'Foo<Bar<int>, int>'
解決方法1
添加的Bar
預先聲明,並創建一個模板別名Bar2
。定義memberFoo
和f
當
template <template <typename> class P, typename T>
class Foo {
P<T>* baz;
};
template<typename T> class Bar;
template <typename U> using Bar2 = Bar<U>;
template <class T>
class Bar {
Foo<Bar2, T> memberFoo;
void makeFoo() {
Foo<Bar2, T>* f = new Foo<Bar2, T>();
}
};
Foo<Bar, int> globalFoo;
向前聲明和使用模板別名迫使編譯器使用的Bar
的非特化版本,而它默認使用非專業化:對於這個編譯,baz
必須是指針版本的定義爲globalFoo
。
解決方法2
此解決方案是基於@ user5800314的答案。我覺得沒有必要重新陳述他的解決方法,但我確實認爲值得注意的是它的工作原因。
我讀過關於注入類名和C++ 11的similar SO question,但是這裏最重要的區別是我的代碼不能在g ++上編譯,而他們的代碼卻沒有。我不認爲這個問題是缺少注入類名的實現。我相信這個解決方法,因爲使用::Bar
代替Bar
再次強制編譯器來訪問,而不是訪問的Bar
本地(專業)版的Bar
全球(非特)版本修復了編譯錯誤。
解決方法3
指定Foo
爲具有類(或類型名稱)模板參數,而不是一個模板的模板參數,並且是明確的關於哪個專業化每當使用Foo
模板被使用。這也要求baz
是一個指針,並且,它不使用模板類型:通過要求一個特定的類提供給Foo
模板
template <class P, typename T>
class Foo {
P* baz;
};
template <class T>
class Bar {
Foo<Bar, T> memberFoo;
void makeFoo() {
Foo<Bar, T>* f = new Foo<Bar, T>();
}
};
Foo<Bar<int>, int> globalFoo;
這種解決方法解決了的模板的模板參數潛在的混亂的。此解決方法在某些情況下可能無法使用,但在其他情況下可能是一個優雅的解決方案。以我的情況爲例,我不需要從Bar
以外實例化Foo
的實例,所以這是解決編譯錯誤的一個非常好的方法。
P.S.我真的想貸記@ user5800314,因爲他的變通辦法工作,但是我在這裏提供一個不同的解釋,因爲我在這裏提供的解釋是什麼,我相信是正確的,我不覺得我可以標記@ user5800314的答案已被接受。
我認爲問題是,定義中'Bar',原名'Bar'指*此*專業化 - 那就是'酒吧' - 而不是模板作爲一個整體。一種解決方法:添加使用BAR2 =酒吧'模板;在''的定義Bar'頂部,並使用'Bar2'到位Bar'的'你需要參考非特模板。 –
這似乎是遞歸的。 Bar有一個Foo成員,但是Foo是模板化的,因此它具有與它所屬的類完全相同的Bar成員。因此,酒吧包含自己,這是不允許的。特定的錯誤是由於在定義期間嘗試使用Bar作爲模板模板參數導致的,我認爲沒有前向聲明。 –