[英]Can standard container templates be instantiated with incomplete types?
有時用不完整類型實例化標准容器以獲得遞歸結構是有用的:
struct multi_tree_node { // Does work in most implementations
std::vector< multi_tree_node > child;
};
struct trie_node { // Does not work in most implementations
std::map< char, trie_node > next;
};
這往往有效,因為容器沒有value_type
類型的成員或按值傳遞或返回任何value_type
對象的成員函數。 標准似乎並沒有對不完整的模板參數說太多,但在 C++11 §17.6.4.8 [lib.res.on.functions] 下有一點,“對其他函數的要求”:
特別是,在以下情況下效果未定義: ...如果在實例化模板組件時將不完整類型 (3.9) 用作模板參數,除非該組件特別允許。
即使實例化不在塊范圍內,這是否會使上述構造非法? 這是否屬於“用於實例化標准庫模板組件的類型的操作”(也是 17.6.4.8)? 或者,當所有特別要求的實例化都成功時,庫實現是否被禁止導致模板實例化可能會因不完整的類型而失敗?
編輯:由於只有函數可以調用和實例化其他函數,因此將“對類型的操作……”限制為塊范圍內的操作似乎使成員函數的內容比簽名和成員類定義的內容具有更嚴格的要求。 畢竟,在類型完成之前對multi_tree_node
做任何事情當然沒有意義。 這擴展到std::unique_ptr
,它明確支持不完整的類型參數,即使在塊作用域中使用也是如此。
編輯 2:為我服務,因為我不費心去測試trie_node
示例——我以前什至嘗試過。 它與@Ise鏈接的文章中的破損示例相同。 然而,雖然這篇文章似乎理所當然地認為“沒有這樣的東西可以工作”,但解決方案對我來說似乎很簡單—— std::map
的內部tree_node
類應該是一個非成員模板,而不是一個成員非模板類.
無論如何,那篇文章很好地確立了設計意圖,所以我想我對“功能要求”子標題下的挑剔僅此而已。
這是我的解釋嘗試:
該標准只是簡單地說你不能這樣做,即使任何給定的具體實現可能沒有問題支持這樣的構造。 但是想象一下,如果有人想編寫一個“小向量”優化,其中一個向量總是包含空間,比如五個元素。 你馬上就會遇到麻煩,因為你有一個自我參照類型。 即使向量根據值類型的大小采用某種靜態分支,這也是一個問題。
因此,為了不排除實現包含這樣的結構,標准只是說你必須只使用完整的類型。 換句話說,大多數容器僅包含指向值類型的引用或指針這一事實是實現細節而不是標准要求。
只是為了澄清這一點:如果您定義自己的類模板,則完全有可能以明確支持不完整類型的方式設計它。 標准中的一個例子是std::unique_ptr
,它對不完整的類型參數T[]
(甚至void
)非常滿意。
個人感覺17.6.4.8/2中instantiating的說法有點含糊,但是根據這篇文章,標准的意圖似乎不允許使用標准容器的遞歸數據類型。
在相關說明中,VC2005 為class C { std::deque< C > x; };
發出錯誤class C { std::deque< C > x; };
class C { std::deque< C > x; };
, 而它編譯class C { std::vector< C > x; };
class C { std::vector< C > x; };
...
但是,在我的理解中,這個限制只是為了擴大標准容器的實現自由度。 因此,正如Kerrek SB 所提到的,可以存在允許遞歸數據結構的容器,而Boost.Container似乎提供了這種功能。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.