2017-02-10 38 views
0

在我的項目中,我使用了多個枚舉類,我需要根據需要使用它們輕鬆地進行轉換。他們基本上描述相同的事物,但命名不同,以使代碼更容易處理。下面是枚舉類:爲枚舉類重載轉換運算符

enum class tetroType { 
    None, I, O, T, J, L, S, Z 
}; 

enum class gridBlock { 
    Empty, Blue, Green, Orange, Purple, Red, Teal, Yellow 
}; 

在tetroType每個值對應於網格塊的值(FE tetroType :: I =網格塊:: TEAL),但所述第一保持關於tetronimo的形狀的信息(在tetronimo類),第二個保存塊的顏色信息(在網格類中)。我知道我可以使用一個枚舉,但這樣你就不會丟失任何信息。如果可能的話,我也需要將它轉換成字符串。這是我想如何使用它:

gridBlock grid = (gridBlock)tetroType::I; 
string texture = (string)grid; 

現在,我已經設置它的方式是這樣的。我使用這個開關的,每當我需要一個枚舉轉換爲另一種或成字符串其他方法中間:

switch (type) { 
case tetroType::I: 
    block = gridBlock::Teal; 
    break; 
case tetroType::O: 
    block = gridBlock::Yellow; 
    break; 
case tetroType::T: 
    block = gridBlock::Purple; 
    break; 
case tetroType::J: 
    block = gridBlock::Blue; 
    break; 
case tetroType::L: 
    block = gridBlock::Orange; 
    break; 
case tetroType::S: 
    block = gridBlock::Green; 
    break; 
case tetroType::Z: 
    block = gridBlock::Red; 
    break; 
case tetroType::None: 
    block = gridBlock::Empty; 
} 
+1

鑄造不應該「輕鬆」完成。它*應該*是詳細和明確的,這樣你就不會過於寬鬆地施放。必須編寫'gridBlock grid = toGridBlock(tetroType :: I)'和'string texture = toString(grid);''是一件好事*。 –

+0

我一直在尋找最優雅和正確的方式來做到這一點,我已經有了將一個轉換爲另一個的功能,但我不確定這是否是正確的方式。此外,該功能應該在哪裏?它應該在頭文件中與枚舉聲明一起使用嗎?這就是爲什麼我認爲如果可能的話,演員將是最優雅的解決方案。 –

+0

這是基於意見的,但個人而言,我更喜歡在自己的頭文件中使用轉換函數,所以我只需要在需要時包含它們。再次,標準庫本身不(總是)這樣做。例如,''包含'std :: string' *和*各種'std :: to_string'函數。 –

回答

1

答案很簡單:不使用enum class,使用普通enum相反,它們可以被隱式轉換到其基本類型(默認int)。

在C++ 11,enum class是一個強大的別名,其中HAS被鑄造而成。

0

如果你接受這樣的事實,你必須保持兩個枚舉一致的其他的一個定義,使每個gridBlock需要從tetroType一個值,那麼您可以覆蓋operator==在比較無縫地使用它們,覆蓋不同運營商(例如<<=)模仿不同類型之間的分配。

事情是這樣的:

#include <iostream> 
#include <type_traits> 
#include <cassert> 

using namespace std; 

enum class tetroType { 
    None, I, O, T, J, L, S, Z 
}; 

enum class gridBlock { 
    Empty = static_cast<std::underlying_type<tetroType>::type>(tetroType::None), 
    Blue = static_cast<std::underlying_type<tetroType>::type>(tetroType::I), 
    Green = static_cast<std::underlying_type<tetroType>::type>(tetroType::O), 
    Orange = static_cast<std::underlying_type<tetroType>::type>(tetroType::T), 
    Purple = static_cast<std::underlying_type<tetroType>::type>(tetroType::J), 
    Red = static_cast<std::underlying_type<tetroType>::type>(tetroType::L), 
    Teal = static_cast<std::underlying_type<tetroType>::type>(tetroType::S), 
    Yellow = static_cast<std::underlying_type<tetroType>::type>(tetroType::Z) 
}; 

bool operator==(const tetroType& t, const gridBlock& g) { return static_cast<gridBlock>(t) == g; } 
bool operator==(const gridBlock& g, const tetroType& t) { return static_cast<gridBlock>(t) == g; } 

bool operator!=(const tetroType& t, const gridBlock& g) { return static_cast<gridBlock>(t) != g; } 
bool operator!=(const gridBlock& g, const tetroType& t) { return static_cast<gridBlock>(t) != g; } 

gridBlock& operator<<=(gridBlock& g, tetroType t) { g = static_cast<gridBlock>(t); return g; } 
tetroType& operator<<=(tetroType& t, gridBlock g) { t = static_cast<tetroType>(g); return t; } 

int main() { 
    tetroType t1 = tetroType::I, t2 = tetroType::O; 
    gridBlock g1 = gridBlock::Blue, g2 = gridBlock::Green; 

    gridBlock g3; 
    g3 <<= t1; 
    tetroType t3; 
    t3 <<= g2; 


    assert(t1 == g1); 
    assert(t1 != g2); 
    assert(g3 == t1); 
    assert(t3 == g2); 

    return 0; 
} 

雖然這種解決方案簡潔,這是相當神祕和晦澀難懂,所以你最好的文檔這種行爲清楚。但一般來說,enum class對於像operator<<=這樣的運算符是很安全的,因爲它們在任何情況下都沒有定義。

請注意,您可以在值之間使用自定義映射,但如果您不需要它們,因爲您可以使用另一個值初始化一個值,則無需手動映射它們。