简体   繁体   中英

Can I overload operators on enum types in C++?

For example, if I have:

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);
}

Because if I do not define such operators it is actually legal to write day*3 and it would be translated into 6?

So is it legal?

At least gcc and intel compiler accept this without a warning.

Clearification:

I do not want default arithmetic operations, I want my own operations that return non-integer type.

Yes, operator overloading can be done on enum and class types. The way you do it is fine, but you should use + to promote the enumeration, instead of *-1 or something (the purpose ultimately is to avoid infinite recursion because -t ):

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

This will scale well to other operations. + will promote the enumeration to an integer type that can represent its value, and then you can apply - without causing infinite recursion.


Notice that your operator* does only allow you to do enum_type * integer , but not the other way around. It may be worth considering the other direction too.

Also notice that it's always a bit dangerous to overload operators for operands that builtin-operators already accept (even if only by implicit conversions). Imagine that distance has a converting constructor taking int (as in distance(int) ), then given your operator/ the following is ambiguous

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

For this, maybe it's better to make field_type a real class with the appropriate operators, so that you can exclude any of such implicit conversions from begin on. Another good solution is provided by C++0x's enum class , which provides strong enumerations.

If you are asking is this code legal:

enum A {
    x,y
};

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

The answer is unfortunately "yes". There is an implicit conversion from enum values to integers.

Well, the answer to your question about day * 3 is: yes, you can do it. You don't need any operator overloading for that. And the result will be 6 . However, this will work by converting your day constant to int type, performing multiplication within the int type and giving the result of type int , ie that 6 is an int . Which rises the next question: Are you OK with it being an int ? What are you planning to do with that 6 afterwards? If an int is OK for your purpose, then you don't need to do anything.

However, it is possible that you actually want to obtain the result of field_type type from day * 3 . You see, in C++ int type is not explicitly convertible to enum types. So this will compile and work

int product = day * 3;

but this will not

field_type product = day * 3; // ERROR

You can force the latter to compile by using an explicit cast

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

or you can start playing with operator overloading, like

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

Note, that the implementation of the overloaded operator still relies on a cast, so this is just a way to make the "main" code of your program look cleaner, by encapsulating the ugly casts into dedicated operators (nothing's wrong with it).

As a pedantic side note, I'd like to add that there are certain formal dangers in trying to squeeze the results of integer arithmetic operations into a enum type (if that's what you want; maybe you don't, since you seem to be using some other type foo for the result providing no details about it). The range of values a enum object can represent is [roughly] determined by the maximum (by magnitude) value of enum constant rounded to the next highest (by magnitude) number of the form 2^N-1 . In your case the highest value is day equal to 2, which means that your enum is guaranteed to represent values up to 3 accurately. If you try to convert 6 to your enum type the result is unspecified (although it will normally work "as expected" in practice).

Yes it is legal. ENUM will automatically turns values into INT.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM