我處於兩個類的定義之間存在循環依賴循環的情況,其中(據我所知)兩個類都需要另一個類型爲完整類型才能正確定義它們。假設sizeof(std :: unordered_map <std :: string,T>)在所有T中都是相同的?
簡單的說,我需要的是怎麼回事的簡化版本:
struct Map;
struct Node {
// some interface...
private:
// this cannot be done because Map is an incomplete type
char buffer[sizeof(Map)];
// plus other stuff...
void* dummy;
};
struct Map {
// some interface...
private:
// this is Map's only member
std::unordered_map<std::string, Node> map_;
};
其實比上述更復雜,因爲Node
實際上將是一個變量類型(類似於boost::variant
情況)使用placement new來顯式地構造預分配的多種對象中的一種(並且具有正確的對齊,我在此簡化中忽略)緩衝區:因此緩衝區不完全是sizeof(Map)
,而是一些計算出的常量,這取決於sizeof(Map)
。
顯然,問題是sizeof(Map)
僅在Map
只是前向聲明時纔可用。此外,如果我更改聲明的順序以首先轉發聲明Node
,那麼編譯Map
失敗,因爲std::unordered_map<std::string, Node>
不能在Node
是不完整類型時實例化,至少在我的Ubuntu上使用GCC 4.8.2。 (我知道這取決於的libstdC++版本比GCC版本的更多,但我不知道易如何找到...)
作爲替代方案,我考慮了以下解決方法:
struct Node {
// some interface...
private:
// doing this instead of depending on sizeof(Map)
char buffer[sizeof(std::unordered_map<std::string, void*>)];
// other stuff...
void* dummy;
};
struct Map {
// some interface...
private:
// this is Map's only member
std::unordered_map<std::string, Node> map_;
};
// and asserting this after the fact to make sure buffer is large enough
static_assert (sizeof(Map) <= sizeof(std::unordered_map<std::string, void*>),
"Map is unexpectedly too large");
這基本上依賴於假設std::unordered_map<std::string, T>
是所有T的大小相同,這似乎從我使用GCC的測試中保持不變。
我的問題是這樣三個方面:
是否有在C++標準的任何要求,這個假設是成立的? (我假設沒有,但如果有,我會驚喜...)
如果不是,它是幾乎安全假設它適用於所有合理實現真正反正,那靜態斷言在我修改後的版本里永遠不會開火?
最後,有沒有更好的解決這個問題,我沒有想到?我敢肯定,這可能有一些很明顯我可以做的,而不是說我沒有想到的,但不幸的是,我不能想什麼......
評論不適用於擴展討論;這個對話已經[轉移到聊天](http://chat.stackoverflow.com/rooms/77815/discussion-on-question-by-trantorian-practically-safe-to-assume-sizeofstdunor)。 – Taryn