2012-05-04 69 views
5

假設我有下面的類模板:含1指針struct的大小

template<typename T> 
struct Wrapper { 
    T* t_; 
    static void check() { 
    static_assert(sizeof(Wrapper<T> == sizeof(T*), "Illegal assumption"); 
    } 
}; 

我在C99標準看一個在C++ 03標準,並不能找到一個擔保我的假設在表達static_assert。我用Visual C++ 2008和2010(32位)和linux上的gcc(64位)使用了幾個編譯器選項嘗試了它,並發現我的假設得到了確認。

我的問題是:

  • 是我的假設合理的Visual C++ 2008/2010/11(窗口)?
  • 對於gcc 4. *(linux)?
  • 對於編譯器標誌的任何組合?
  • 你知道任何編譯器/平臺的這種假設不適用嗎?

我想編譯器可能會添加一些填充到結構,例如用於調試目的。但是有沒有一個編譯器可以實現這個功能?

編輯:所以,當你問這裏是我想達到的目標:
我有以下簽名的成員函數:

Someclass* OtherClass::fn(); 

我想改變簽名是這樣的:

Wrapper<Someclass> OtherClass::fn(); 

這個包裝就像一些智能指針,它關心指針的生命週期,因此它在超出範圍時釋放它。由於該函數是通過dll邊界調用的,因此我想確保返回的值(現在是具體類型,而不僅僅是啞指針)在所有情況下(即編譯器設置等)與指針具有相同大小將會。該計劃/希望是支持調試/發佈應用程序/ dll構建的所有組合。
正如你可能會問:不,我不能使用boost :: shared_ptr <>,std :: shared_ptr <>,std :: unique_ptr <>之類的,因爲我們不想暴露對dll用戶的提升而我們目前還不支持C++ 11。

+1

您是否考慮過虛函數/繼承? – PlasmaHH

+0

所以...你希望我們在所有這些編譯器和平臺上爲你測試代碼嗎? –

+1

不,他可能想知道某人是否已經做了類似的事情,或者如果這是隱含在標準或編譯器文檔的其他地方。 – Tibor

回答

3

如果你想假設它,你有一個編譯時檢查,然後繼續。據推測,你從這樣做中獲得了一些好處。

您不能保證任何關於填充的內容,但通常使用填充來獲得對齊,以便該類型的數組使數組的每個成員(以及結構的每個成員)都正確對齊。本地指針通常已經是對齊的正確大小,因此不需要填充,但不能保證。

這不是你可以用gcc檢查的東西 - 它取決於目標體系結構,而不僅僅是編譯器。

+0

我只想確保知道我必須關心的事情,我可以依賴的以及我必須省略的事項。 – nriedlin

+0

如果你的假設不正確,你可以依靠你的斷言解僱。你永遠不能依賴於它永遠不會觸發編譯器(或版本)和目標的新組合。 –

1

尋找到標準我發現了兩個有趣位§9.2 [class.mem]

17/兩個標準佈局結構(第9節)類型是佈局兼容如果它們具有相同數量的非靜態數據成員和相應的非靜態數據成員(按聲明順序)具有與佈局兼容的類型(3.9)。

因此,只有一個指針的兩個struct佈局兼容(因此,如果您的斷言適用於此類型,它適用於所有類型)。

20/指向一個標準佈局結構對象,適宜地轉換使用的reinterpret_cast,點到它的初始成員(或如果該構件是一個位域,然後以在其駐留的單元),反之亦然。 [注意:因此在標準佈局結構對象中可能存在未命名的填充,但在開始時並不需要填充,以實現適當的對齊。 - 注意]

在說明中我們瞭解到,在結構的開始處不能有填充。


根據你的目標,20/可能就足夠了。這意味着這個工作:

void check(T* t) { 
    Wrapper<T>* w = reinterpret_cast<Wrapper<T>*>(t); 
    assert(w->t_ == t); 
} 
1

我想說你的假設對大多數編譯器和標誌是合理的。

對於任何T,編譯器都能夠創建T的數組,因此它必須是連續的,所以它必須能夠在沒有填充的情況下創建它。因此,將它放入結構中的任何填充都是純粹的可選項,而不是可能需要的。另一方面,我相當肯定沒有一個C或C++標準能夠保證你所要求的。 最接近來保證它將源於這樣一個事實,即在C++中它是一個標準佈局結構,它限制C++編譯器像C編譯器一樣佈置字段,所以成員必須是升序而沒有在開始時填充 - 但是在成員之間和/或在最後一個成員之後填充仍然是允許的。底線:如果你有一個指向第一個成員的指針,你可以安全地轉換爲指向struct的指針(反之亦然)。如果你創建一個數組並將其編入索引,就好像它是另一個數組一樣 - 你可以獨立工作 - 它的工作機會相當好,但我很確定標準沒有保證它。