由於讀了很多警告不要使用工會這樣的:訪問像數組一樣的成員?
union rgba
{
struct
{
uint8_t r, g, b, a;
} components;
uint8_t index[4];
uint32_t value;
};
,因爲這是不確定的行爲,我決定讓事情變得簡單,像這樣:
struct rgba
{
uint8_t r, g, b, a;
};
但事有湊巧,有時我確實需要在使用索引的循環中訪問r
,g
,b
和a
,否則我必須分別爲每個組件複製相當長的代碼。
於是我想出了這一點:
struct rgba
{
u8 r, g, b, a;
constexpr u8& operator[](size_t x)
{
return const_cast<u8*>(&r)[x];
}
};
這依賴於假設r
,g
,b
和a
放在線性的方式在記憶裏,在兩者之間沒有隱藏的樣板,而編譯器保留可變順序。
有了這個,我可以訪問組件就像我想:
rgba c;
for (int i = 0; i < 3; i++)
c[i] = i^(i + 7);
c.a = 0xFF;
- 因爲我做了相當大的假設,我敢肯定,這甚至比使用工會的種類較多不確定的行爲雙關語。我對麼?
- 我還能如何實現類似的設計?
- 我想避免寫
c.r() = 5
如果可能,因爲它看起來很有趣。 - 使用訪問器如
c.components[RED]
使用宏,我喜歡避免使用宏。 - 從第2點替換宏,使用枚舉在考慮訪問此類枚舉所需的名稱空間時會看起來很難看。想象一下
c.components[Image::Channels::Red]
。
- 我想避免寫
你爲什麼不使用則'的std ::陣列',應該是安全的,並足夠 –
coincoin
快,因爲訪問它的成分,除非大家都在項目知道顏色模型是BGRA,我需要引入'enum'←見2.3節。 –
反過來這樣做通常會更容易:保留一個包含所有rgba組合的'uint32_t',並提供像'uint8_t r()'等訪問器。在'uint8_t == unsigned char'的情況下,你甚至可以使用別名'uint32_t'帶'uint8_t',àla'uint8_t&r()'。 – dyp