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
, i.e. 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.
精彩评论