簡體   English   中英

重載枚舉類的強制轉換運算符

[英]Overloading cast operator for enum class

在我的項目中,我使用了多個枚舉類,我需要根據需要在何處使用它們輕松地在它們之間進行轉換。 它們基本上描述相同的東西,但命名不同,以使代碼更易於使用。 以下是枚舉類:

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

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

tetroType 中的每個值都對應於 gridBlock 中的一個值(fe tetroType::I = gridBlock::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;
}

簡單的回答:不要使用enum class ,而是使用普通enum ,它們可以隱式轉換為它們的基礎類型(默認int )。

在C ++ 11, enum class是一種強的別名,其必須從鑄造。

您應該考慮將枚舉類作為整數重載(這是 C++ 11 的特性)。

enum class tetroType : int {
    I = 1, O = 2, T = 3, J = 4, L = 5, S = 6, Z = 7, NONE
};

enum class gridBlock : int {
    Blue = 1, Green = 2, Orange = 3, Purple = 4, Red = 5, Teal = 6, Yellow = 9, EMPTY
};

從這里您可以使用 ether C Style typecasting 或 static_cast 編寫基本轉換

gridBlock ConvertTetro(tetroType type){
    return static_cast<gridBlock>(static_cast<int>(type));
}

gridBlock ConvertTetro(tetroType type){
    return (gridBlock)((int)((type)));
}

這將匹配任何網格塊到相等的四元組,如果沒有匹配類型,將默認為 gridBlock::EMPTY。 如果需要,這個函數應該很容易弄清楚如何走另一條路。 從這里開始,您需要匹配兩者之間的 int 值。

您還可以使用 char 值作為字符文字('A'、'b'、'!')使用

enum class enumName : char

只要兩種基礎類型,這就會起作用

如果您接受必須保持兩個枚舉之一的定義與另一個一致的事實,以便每個gridBlocktetroType獲取一個值,那么您可以覆蓋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<<=operator<<=是非常安全的,因為它們在任何情況下都沒有定義。

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM