2011-05-16 31 views
7

我迫切需要找到以下問題的解決方案:...與構造不允許在工會問題

namespace test 
{ 
    template <int param = 0> struct Flags 
    { 
     int _flags; 

     Flags() 
     { 
      _flags = 0; 
     } 

     Flags(int flags) 
     { 
      _flags = flags; 
     } 

     void init() 
     { 

     } 
    }; 

    union example 
    { 
     struct 
     { 
      union 
      { 
       struct 
       { 
        Flags<4096> f; 
       }p1; //error: member 'test::example::<anonymous struct>::<anonymous union>::<anonymous struct> test::example::<anonymous struct>::<anonymous union>::p1' with constructor not allowed in union 

       struct 
       { 
        Flags<16384> ff; 
       }p2; //error: member 'test::example::<anonymous struct>::<anonymous union>::<anonymous struct> test::example::<anonymous struct>::<anonymous union>::p2' with constructor not allowed in union 
      }parts; 

      byte bytes[8]; 
     }data; 

     int data1; 
     int data2; 
    } 
} 


這是令人沮喪,如果我添加標籤,以P1和P2結構,代碼將編譯,但F & FF成員將無法訪問:

... 
struct p1 
{ 
    Flags<4096> f; 
}; 

struct p2 
{ 
    Flags<4096> ff; 
}; 
... 

void test() 
{ 
    example ex; 
    ex.data.bytes[0] = 0; //Ok 
    ex.data.parts.p1.f.init(); //error: invalid use of 'struct test::example::<anonymous struct>::<anonymous union>::p1' 
} 


有什麼辦法,使這項工作不知何故?

回答

8

正如@Als所說,union不能將non-POD定義爲成員數據,還有一種選擇。你仍然可以定義一個指向non-POD的指針作爲union的成員數據。

所以這是允許的:

union 
{ 
    struct 
    { 
     Flags<4096> *pf; //pointer to non-POD 
    }p1; 
    struct 
    { 
     Flags<16384> *pff; //pointer to non-POD 
    }p2; 
}parts; 

但隨後Boost.Variant是一個更好的選擇。

+1

非常感謝,夥計們! – Ryan 2011-05-16 08:43:05

7

當前的C++標準不允許工會內的非POD類型。因此你從gcc得到這個編譯器錯誤。
而不是使用C聯合,您應該使用boost::variant。檢查文檔here

要添加到上面:
新的C++標準(C++ 0X)增加了一個稱爲Unrestricted Unions新功能,該功能支持存儲非POD類型加入到Union。

+0

C++委員會喜歡驚歎號...什麼是不允許non-pod類型的一點? – Calmarius 2013-09-14 08:53:48

0

C++標準2003不允許此(從標準9.5):

與 非平凡構造(12.1),一個 非平凡複製構造的類的對象(12.8) (12.4)或 非平凡複製賦值運算符 (13.5.3,12.8)不能是 聯合體的成員,也不能是此類對象的數組。

但是,C++ 0x允許它,但是,您需要定義自己的構造函數,因爲如果您沒有定義自己的構造函數,默認構造函數將被聲明爲刪除。

從N3291 9.5:

如果 工會的任何非靜態數據成員有一個不平凡的默認 構造函數(12.1),拷貝構造函數 (12.8),移動構造函數(12.8),複製 賦值運算符(12.8),移動 賦值運算符(12.8),或 析構函數(12.4),並集的對應 成員函數必須是 用戶提供的或將被隱含地 刪除(8.4.3),用於工會。

其他人建議Boost.Variant。爲了簡單修復,只需從Flag類中移除構造函數即可。儘管初始化聯合對象時需要手動初始化它,但它不會令人困惑,因爲聯合本質上是一個C特性。