2017-02-10 42 views
0

私のプロジェクトでは、複数の列挙型クラスを使用しています。これらは、使用する場所によって簡単にキャストする必要があります。彼らは基本的に同じことを記述しますが、コードをより使いやすくするために、異なる名前が付けられています。ここで列挙クラスがある:enumクラスのキャスト演算子のオーバーロード

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 ::ティール)が、最初はtetronimoに(tetronimoの形状に関する情報を保持していますクラス)、ブロックの色に関する情報(グリッドクラス)を保持します。代わりに1つの列挙型を使用することはできますが、この方法では情報を失うことはありません。また、可能ならば文字列にキャストする必要があります。これはどのように私がそれを使用したいのですか:

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

今私がそれをセットアップした方法はこれのようです。私は別に、または文字列に1つの列挙型を変換する必要がある時はいつでも、私は他の方法の真ん中にこのスイッチを使用しています:

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

あなたは、各gridBlocktetroTypeからの値をとるようにしますが、他にコヒーレント2つの列挙型の1の定義を保持しなければならないという事実を受け入れるなら、あなたは比較でシームレスにそれらを使用する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<<=のような演算子をオーバーライドするのはかなり安全です。

値の間にカスタムマッピングを使用できますが、必要でない場合は、値を別の値で初期化できるため、手動でマップする必要はありません。

関連する問題