15


0

C ++で列挙型の演算子をオーバーロードできますか?

たとえば、私が持っているなら:

typedef enum { year, month, day } field_type;

inline foo operator *(field_type t,int x)
{
   return foo(f,x);
}
inline foo operator -(field_type t)
{
   return t*-1;
}
int operator /(distance const &d,field_type v)
{
  return d.in(v);
}

そのような演算子を定義しない場合、実際には `day * 3`を記述することは合法であり、6に変換されるためです。

それは合法ですか?

少なくともgccとintelコンパイラは警告なしでこれを受け入れます。

明確化:

デフォルトの算術演算は必要ありません。整数以外の型を返す独自の演算が必要です。

4 Answer


7


はい、演算子のオーバーロードは列挙型およびクラス型で実行できます。 方法は問題ありませんが、列挙を促進するには、「*-1」などの代わりに「+」を使用する必要があります(最終的な目的は、「-t」のため無限再帰を回避することです):

inline foo operator -(field_type t) {
   return -+t;
}

これは、他の操作に合わせて拡張できます。 「+」は列挙をその値を表すことができる整数型に昇格させ、無限再帰を発生させずに「-」を適用できます。

'' '' '

`operator *`は `enum_type * integer`のみを許可しますが、その逆はできないことに注意してください。 他の方向も考慮する価値があるかもしれません。

また、組み込み演算子が既に受け入れているオペランドの演算子をオーバーロードすることは、常に危険であることに注意してください(暗黙的な変換によってのみであっても)。 distance`が( distance(int) `のように)intを取る変換コンストラクターを持っていると想像してください。

// ambiguous: operator/(int, int) (built-in) or
//            operator/(distance const&, field_type) ?
31 / month;

このためには、適切な演算子を使用して `field_type`を実際のクラスにして、そのような暗黙の変換を最初から除外できるようにした方が良いかもしれません。 別の優れたソリューションは、強力な列挙を提供するC ++ 0xの「enumクラス」によって提供されます。


1


あなたが求めている場合、このコードは合法です:

enum A {
    x,y
};

int main() {
    int z = x * y;
}

残念ながら、答えは「はい」です。 列挙値から整数への暗黙的な変換があります。


0


さて、 `day * 3`についてのあなたの質問に対する答えは、はい、できます。 そのために演算子をオーバーロードする必要はありません。 結果は「6」になります。 ただし、これは、「day」定数を「int」型に変換し、「int」型内で乗算を実行し、「int」型の結果を与えることで機能します。 「6」は「int」です。 次の質問が浮上します:「int」であっても大丈夫ですか? その後、その「6」をどうするつもりですか? `int`が目的に合っていれば、何もする必要はありません。

ただし、実際には day * 3`から field_type`型の結果を取得したい場合があります。 ご覧のとおり、C ++では `int`型は明示的に列挙型に変換できません。 これはコンパイルして動作します

int product = day * 3;

しかし、これはしません

field_type product = day * 3; // ERROR

明示的なキャストを使用して、後者を強制的にコンパイルできます

field_type product = (field_type) (day * 3);

または、次のような演算子のオーバーロードで遊ぶこともできます

field_type operator *(field_type lhs, int rhs)
{
  return (field_type) ((int) lhs * rhs)
}

オーバーロードされた演算子の実装は依然としてキャストに依存しているため、これはsoいキャストを専用の演算子にカプセル化することにより、プログラムの「メイン」コードをよりきれいに見せるための単なる方法です(何も問題はありません)。

ちょっとした補足として、整数算術演算の結果をenum型に絞り込もうとすると、ある種の正式な危険性があることを付け加えたいと思います(もしそれがあなたが望むなら、多分あなたはそうではないようです結果に他の型「foo」を使用して、詳細を提供しません)。 enumオブジェクトが表すことができる値の範囲は、[大体] enum定数の最大値(大きさによる)によって、 2 ^ N-1`形式の次に大きい(大きさによる)数に丸められます。 あなたの場合、最高値は2に等しい `day`です。これは、enumが 3`までの値を正確に表すことが保証されていることを意味します。 `6`を列挙型に変換しようとすると、結果は指定されません(実際には通常「期待どおり」に動作しますが)。


-1


はい、合法です。 ENUMは値を自動的にINTに変換します。