2017-06-22 2 views
0

問題が痛いほどよく聞こえます。 は、あなたが列挙型を持っていると仮定しますC++での組み込み型の列挙型への自動変換

enum MyEnum {first, second, third}; 

は今、私はMyEnumに、いくつかのint型に変換します。ナイーブアプローチ

int i = 2; 
MyEnum e = (MyEnum)i; 

そうだとは限りません。まず、2は「第3」に変換され、第2には変換されません。第二に、この変換はダムであり、私はスマートなものを望んでいます。次のように 動機は次のとおりです。

void foo(MyEnum e) { ... } 
... 
foo(2); 

そして、それのfoo()は常に関係なく、この列挙型の実際の値が何であるか2のための「第2」受け取るべきではありません。 2つの明白な解決策があります。

  1. 書き込み変換機能と常には
  2. 過負荷キャスト演算子

第一ソリューション、それを呼び出すには、明らかにひどいです。書き込みをしたくありませんfoo(convetIntToMyEnum(2));

私はfoo(2)を書きます。コンパイラは自動的に変換関数を呼び出します。だから二番目の解決策は私が必要なものです。 'int'が自分のクラスだった場合、キャスト演算子のオーバーロードは簡単です。しかし、int型はintrinsic型です。

私は漠然とその可能性を覚えていますが、それを見つけることはできません。私の金髪の瞬間の治療を感謝します。

+3

「enum MyEnum {first = 1、second、third}}」を実行します。問題が解決しました。 – cdhowie

+0

いいえ、私はそれを望んでいません。具体的には、enumは{first = 0x1000、second = 0x2000 ...}とすることができます。ヒント:enumはHWの設定を表していますので、enum項目の値を自由に選択することはできません。 – Noname

+0

なぜ、0x1000にマッピングされるのでしょうか?それはちょっとばかげている。あなた自身のコードを難読化するというこの奇妙な欲求を本当に追求したいなら、enumの代わりにクラスを使うことを検討してください。またはルックアップテーブル。あるいは、数値を他の数字に変える暗黙的な変換以外の文字通りのもの。 – cdhowie

答えて

3

これはクラスではないため、メンバー関数やコンストラクタを持つことができないため、「キャスト演算子」(通常は「コンバージョンコンストラクタ」または「ユーザー定義変換演算子」)をオーバーロードできません。

あなたはおそらくこのような何かをしたいと思います:

class my_enum 
{ 
public: 
    enum MyEnum {first=0x1000, second=0x2000, third=...}; 

private: 
    MyEnum m_value; 

public: 
    my_enum(int _value) { 
     switch (_value) { 
      case 1: m_value = first; break; 
      case 2: m_value = second; break; 
      case 3: m_value = third; break; 
      default: throw std::invalid_argument("invalid value"); 
     } 
    } 

    operator int() const { 
     switch (m_value) { 
      case first: return 1; 
      case second: return 2; 
      case third: return 3; 
      default:  return 0; 
     } 
    } 
}; 

void foo(my_enum e) 
{ 
    ... 
} 

あなたがいる限り、それは可逆だとして、あなたが望むことintからenum valueにどのようなマッピングを定義することができます。コンストラクタとキャスト演算子は明示的ではないので、これにより必要な暗黙的な変換が可能になります。

+0

明らかにあなたは正しいです。私は古いコードライブラリを見て、 'operator <<'がオーバーロードされていることを知りましたが、キャスト演算子は非常に特別なようです。 しかし、C++ではfoo(&myObj)の代わりにfoo(myObj)を書くことができるだけの関数参照が導入されているように、かなりばかげています。しかし、ネイティブ型から列挙型へのユーザー定義の変換はありません。 – Noname

0

第3の明らかな解決策があります。関数の引数として整数を使用せず、代わりに直接列挙型を使用してください。あなたがそれをしている間、単にenumクラスにしてください!追加ボーナス:コードの明瞭度が向上しました。これは、間違った関数プロトタイプのためにあらゆる種類の予期しない変換を書き始める実際的な理由ではありません。

これらの関数が外部APIから渡された場合は、適切に型付けされた方法でラップしてください。列挙型メンバの生の整数値が必要な場合は、明示的な変換関数を呼び出してください。しかし、ハードウェア自体にアクセスする際にはそのサウンドが必要なので、これらのコールサイトもラップすることができ、上記のすべてのレイヤーで適切なものを自由に使用できます。

+0

私は明示的にコンバータを呼び出すことができます。私のポストを注意深く読んでみると、オプション1として言及していることに気付くでしょう。 しかし、私はコール・コンバータを明示的にしたくありません。 – Noname

+0

あなたが私の答えを慎重に読めば、foo(2)を呼び出さず、代わりにfoo(MyEnum :: second)を呼び出すことに気づくでしょう。あなたが考えるオプションではありません。 – rubenvb

+0

まあ、あなたが必要とすることをしないでください答えは実質的に任意の質問への究極の答えです:)私はネイティブタイプを列挙型に変換する理由があります。 – Noname

関連する問題