2012-03-25 115 views
11

我有這樣一個遞歸類型:模板遞歸類型

template<typename T> 
struct SomeType { 
    std::map<T, SomeType<T>> mapping; 
}; 

SomeType<int> foo; 

這工作正常,但更換std::mapstd::unordered_map導致編譯錯誤,由於不完全類型。我(或gcc)在某處發生錯誤嗎?或者這只是標準的一部分?

我還想通過模板參數(例如std::stackstd::queue)確定內部容器,但是我找不到一種方法來完成它,因爲這需要定義SomeType。

不完整的例子:

template<typename T, typename C = std::map<T, SomeType<[???]>>> 
struct SomeType { 
    C mapping; 
}; 

SomeType<int, [???]> foo; 

我知道這可以運行間接來完成,但是這不是我要找的。

+1

標準庫容器模板需要實例化他們完整的類型;一切都是未定義的行爲。你必須忍受這一點。不過,您可以使用pimpl解決方案來解決這個問題。 – 2012-03-25 13:45:44

+0

@KerrekSB是這樣嗎?該死,我經常編寫n-ary樹,其節點是用'std :: vector children'來實現的。 – 2012-03-25 13:46:42

+0

@KonradRudolph:好的,你必須確保在實例化時類型已經完成。這可能是一個微妙的問題。 – 2012-03-25 13:57:51

回答

7

您的課程在其定義的最終}之前的任何地方都不完整。因此mapping成員在其類型的模板參數中使用不完整類型SomeType

The standard does not allow this, and it is pure luck that it works with some STL containers.

你的第二個問題屬於相同的答案下 - 它是非法的這樣做擺在首位。

+0

嗯。不幸的是,我不理解這篇文章中關於爲什麼'std :: map '不完整的類型原則上不能工作的論點。這不是很像'std :: vector >',哪個*可以*原則上工作('std :: pair '不完整)?其他容器也一樣。 – 2012-03-25 16:23:22

+0

如果這需要解釋,我建議打開一個聊天室,這並不難,只是不適合評論部分...現在,我該如何明確地打開一個聊天室關於這... – Irfy 2012-03-25 16:31:11

+1

讓我們在這裏聊天:http:///chat.stackoverflow.com/rooms/9282/stl-with-incomplete-types – Irfy 2012-03-25 16:34:00

4

出於顯而易見的原因,您無法定義具有遞歸默認參數的模板。您也不能在不完整類型上實例化標準庫容器模板,因爲標準是這樣說的(否則它是未定義的行爲)。通常PIMPL方法可能會有所幫助,但是:

#include <map> 
#include <memory> 
template <typename T> class SomeType 
{ 
    typedef std::map<T, SomeType<T>> map_type; 
    typedef std::unique_ptr<map_type> map_ptr; 
    map_ptr pimpl; 
public: 
    SomeType() : pimpl(new map_type) { } 
}; 
+1

boost :: container庫爲大多數STL類型提供了替代方案,這些類型允許不完整類型的遞歸容器。它目前不提供unmarked_map – mark 2012-03-26 07:47:02

+0

@mark:謝謝,這很好理解! – 2012-03-26 08:03:55

3

雖然你不能使用不完全類型與容器,你可以用智能指針做到這一點。 雖然你不能創建未定義類型參數模板類型,你可以使用一些技巧,在這裏:

template<typename T, template <typename U, typename V, typename... Args> class Container = std::unordered_map > 
struct SomeType { 
    Container<T, std::unique_ptr<SomeType> > mapping; 
}; 
+0

是否有可能更改第一行,使Container的默認值爲std :: vector? – 2015-01-25 11:36:44

+0

@NielsLohmann,從技術上講,你可以編寫'template class Container = std :: vector>',但它會與'std :: unordered_map'不一致。因爲地圖是_assosiative_ conrtainer,矢量只是一個數組。 – Lol4t0 2015-01-25 20:15:58