我可以在C ++中重写enum类型的运算符吗?

时间:2010-03-06 17:40:50

标签: c++ operator-overloading enums

例如,如果我有:

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编译器在没有警告的情况下接受这个。

Clearification:

我不想要默认算术运算,我希望自己的操作返回非整数类型。

4 个答案:

答案 0 :(得分:7)

是的,可以在枚举和类类型上完成运算符重载。你这样做的方式很好,但你应该使用+来推广枚举,而不是*-1或其他东西(最终的目的是避免无限递归,因为-t):

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

这将很好地适用于其他操作。 +会将枚举提升为可以表示其值的整数类型,然后您可以应用-而不会导致无限递归。


请注意,您的operator*仅允许您执行enum_type * integer,但不允许您执行distance。也许值得考虑另一个方向。

另请注意,对于内置运算符已经接受的操作数重载运算符总是有点危险(即使只是通过隐式转换)。想象一下,distance(int)有一个转换构造函数采用int(如operator/),然后给出// ambiguous: operator/(int, int) (built-in) or // operator/(distance const&, field_type) ? 31 / month; 以下是不明确的

field_type

为此,也许最好使用适当的运算符使enum class成为一个真正的类,以便您可以从begin开始排除任何此类隐式转换。 C ++ 0x的{{1}}提供了另一个很好的解决方案,它提供了强大的枚举。

答案 1 :(得分:1)

如果您要求此代码合法:

enum A {
    x,y
};

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

答案很遗憾“是”。存在从枚举值到整数的隐式转换。

答案 2 :(得分:0)

嗯,关于day * 3的问题的答案是:是的,你可以做到。您不需要任何运算符重载。结果将是6。但是,这可以通过将day常量转换为int类型,在int类型中执行乘法并提供类型int的结果,即6来实现。是int。这提出了下一个问题:你是int还可以吗?您之后计划用6做什么?如果int可以满足您的目的,那么您无需执行任何操作。

但是,您实际上可能希望从field_type获取day * 3类型的结果。你看,在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)
}

请注意,重载运算符的实现仍然依赖于强制转换,因此这只是通过将丑陋的强制转换封装到专用运算符中来使程序的“主要”代码看起来更清晰的一种方法(没有任何问题) )。

作为一个迂腐的旁注,我想补充说,尝试将整数算术运算的结果压缩为枚举类型存在某些正式的危险(如果这是你想要的;也许你没有,因为你似乎正在使用其他类型foo来获得结果,而不提供有关它的详细信息)。枚举对象可以表示的值范围[粗略]由枚举常量的最大值(按幅度)确定,舍入为2^N-1形式的下一个最高(按幅度)数。在您的情况下,最高值day等于2,这意味着您的枚举可以保证准确表示最多3的值。如果您尝试将6转换为枚举类型,则结果未指定(尽管它通常在实践中“按预期”工作)。

答案 3 :(得分:-1)

是的,这是合法的。 ENUM将自动将值转换为INT。