2011-04-19 20 views
3

我想以兼容GCC 4.3.4和Clang 2.9的方式使用命名屬性來初始化結構。可以使用C++中的可移植方式使用命名屬性初始化POD結構嗎?

struct A { 
    unsigned int x; 
}; 

// GCC: error: expected primary-expression before '.' token 
A a = { 
    .x = 0xdeadbeef; 
}; 

// Clang: error: use of GNU old-style field designator extension [-Werror,-Wgnu-designator] 
A a = { 
    x : 0xdeadbeef; 
}; 

我不能添加-Wno-GNU的標誌CXXFLAGS因爲當時GCC將拒絕建立,因爲它不知道該標誌。如果沒有命名屬性,我不能使用初始化列表,因爲如果API更改,我們將遇到嚴重問題。

我需要的解決方案必須符合C++標準,同時保留這樣一個事實,即如果新屬性出現在結構中,它們應該是未初始化的(或最好是NULL)。結構是第三方,我不能以任何方式改變它們。

+0

我不知道,針對特定的工具鏈的兩個特定版本算作是「便攜式」。 – 2011-04-19 12:39:57

+1

「我需要的解決方案必須符合C++標準」 - 這是一個問題,因爲這些都不是標準的C++。 C++ 03沒有通過命名成員進行初始化,而GCC 4.3.4在其中沒有太多C++ 0x。 – 2011-04-19 13:08:36

回答

4

不,您不能命名這些值,只需按順序給它們。

A a = { 42 }; 

如果新的字段在結構的末尾添加,它們將被清零。

+0

可悲的是,供應商沒有保證他們會在最後添加它們。 – 2011-04-19 12:30:15

+0

@DavidHolm:這就是爲什麼你需要一個合適的版本控制系統。 – 2011-04-19 12:40:44

+2

您也許可以通過編寫一個函數'A make_A(unsigned int x){A a = {0};}來處理訂單問題。 a.x = x;返回一個; }'。現在您可以輕鬆地寫入'A a = make_A(0xdeadbeef);',並且如果供應商在'x'之前添加成員,則它將被初始化爲零。然後你可以將它作爲默認參數添加到'make_A'中,所以params的順序是它們被添加的順序,而不是結構中的順序。但是您不再使用初始化表達式中的已命名成員,因此我不知道這是否可以接受。 – 2011-04-19 13:15:13

2

你可以做這樣的事情:

#if THIS_IS_GCC 
    #define INIT_ATTR(x,y) x : y; 
#elif THIS_IS_LLVM 
    #define INIT_ATTR(x,y) .x=y; 
#else 
    #error Can't do it :/ 
#endif 

A a = { 
    INIT_ATTR(x,0xdeadbeef) 
}; 

但是這真的不是標準的C++。

什麼不好:

A a; 
a.x = y; 
+1

它也不是標準英語。 – 2011-04-19 12:41:35

+0

這應該工作,但我懷疑它會通過代碼審查:( – 2011-04-19 12:51:14

+1

@DavidHolm你抱怨說,你想要的交叉編譯器兼容的代碼,遵守標準,現在_clean足以讓其他人會喜歡它。 ,你需要排列你的優先次序,有時候並不是所有的約束都能同時滿足,那就是生活。 – 2016-01-08 10:21:52

相關問題