views:

392

answers:

4

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.

A: 

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

xis19
that is exactly I do not want. I ask is it legal to overload?
Artyom
@Artyom: Wrong. You explictly asked "If I **do not define** such operators it is actually legal to write `day*3` and it would be translated into `6`?". This apparently is the answer to *that* question of yours.
AndreyT
+1  A: 

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.

anon
+4  A: 

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.

Johannes Schaub - litb
Thanks, it was really helpful, I just wanted to be sure that I do not do something that is not really well defined.
Artyom
A: 

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).

AndreyT
"since you seem to be using some other type foo" indeed I just not mentioned it is just a simple class that hold both enum and off set so I can write `date+=year*3+month*3+week` where some type would hold the full offsets.
Artyom
Your `operator*` implementation will end up in endless recursion
Johannes Schaub - litb
@Johannes: You are right. Fixed.
AndreyT