我可以在 C++ 中重载枚举类型的运算符吗?
例如,如果我有:
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 编译器接受这一点而不发出警告。
说明:
我不想要默认的算术运算,我想要我自己的返回非整数类型的运算。
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.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
是的,可以对枚举和类类型进行运算符重载。你这样做的方式很好,但你应该使用
+
来促进枚举,而不是*-1
或其他东西(最终的目的是避免无限递归,因为 < code>-t):这将很好地扩展到其他操作。
+
会将枚举提升为可以表示其值的整数类型,然后您可以应用-
而不会导致无限递归。请注意,您的
operator*
只允许您执行enum_type * integer
操作,反之则不然。也许也值得考虑其他方向。另请注意,为内置运算符已接受的操作数重载运算符总是有点危险(即使仅通过隐式转换)。想象一下
distance
有一个采用 int 的转换构造函数(如distance(int)
中所示),然后给定您的operator/
,以下内容是不明确的,也许最好使用适当的运算符使
field_type
成为一个真正的类,以便您可以从一开始就排除任何此类隐式转换。另一个很好的解决方案是 C++0x 的enum class
提供的,它提供了强枚举。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
):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 doenum_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 indistance(int)
), then given youroperator/
the following is ambiguousFor 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'senum class
, which provides strong enumerations.如果您问此代码是否合法:
不幸的是,答案是“是”。存在从枚举值到整数的隐式转换。
If you are asking is this code legal:
The answer is unfortunately "yes". There is an implicit conversion from enum values to integers.
是的,这是合法的。 ENUM 会自动将值转换为 INT。
Yes it is legal. ENUM will automatically turns values into INT.
嗯,关于
day * 3
的问题的答案是:是的,你可以做到。为此,您不需要任何运算符重载。结果将是6
。但是,这可以通过将day
常量转换为int
类型、在int
类型内执行乘法并给出类型的结果来实现。 int
,即6
是一个int
。这就提出了下一个问题:你同意它是一个int
吗?之后您打算如何处理6
?如果int
适合您的目的,那么您不需要执行任何操作。但是,有可能您实际上想要获取
day * 3
的field_type
类型的结果。您会看到,在 C++ 中,int
类型不能显式转换为枚举类型。因此,这将编译并工作,但这不会
您可以通过使用显式强制转换来强制后者进行编译
,或者您可以开始使用运算符重载,例如
注意,重载运算符的实现仍然依赖于强制转换,所以这是只是一种使程序的“主”代码看起来更干净的方法,通过将丑陋的强制转换封装到专用运算符中(这没有任何问题)。
作为迂腐的旁注,我想补充一点,尝试将整数算术运算的结果压缩到枚举类型中存在某些形式上的危险(如果这是您想要的;也许您不想要,因为您似乎是使用其他类型
foo
来获取结果,但未提供有关详细信息)。枚举对象可以表示的值范围[粗略地]由枚举常量的最大值(按大小)确定,舍入到下一个最高(按大小)形式的数字2^N-1
。在您的情况下,最高值为day
等于 2,这意味着您的枚举保证准确表示高达3
的值。如果您尝试将6
转换为枚举类型,则结果是未指定的(尽管在实践中它通常会“按预期”工作)。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 be6
. However, this will work by converting yourday
constant toint
type, performing multiplication within theint
type and giving the result of typeint
, i.e. that6
is anint
. Which rises the next question: Are you OK with it being anint
? What are you planning to do with that6
afterwards? If anint
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 fromday * 3
. You see, in C++int
type is not explicitly convertible to enum types. So this will compile and workbut this will not
You can force the latter to compile by using an explicit cast
or you can start playing with operator overloading, like
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 form2^N-1
. In your case the highest value isday
equal to 2, which means that your enum is guaranteed to represent values up to3
accurately. If you try to convert6
to your enum type the result is unspecified (although it will normally work "as expected" in practice).