例如,如果我有:
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:
我不想要默认算术运算,我希望自己的操作返回非整数类型。
答案 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。