我可以在 C++ 中重载枚举类型的运算符吗?

发布于 2024-08-24 16:09:15 字数 476 浏览 4 评论 0原文

例如,如果我有:

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

萌面超妹 2024-08-31 16:09:15

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

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

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


请注意,您的 operator* 只允许您执行 enum_type * integer 操作,反之则不然。也许也值得考虑其他方向。

另请注意,为内置运算符已接受的操作数重载运算符总是有点危险(即使仅通过隐式转换)。想象一下 distance 有一个采用 int 的转换构造函数(如 distance(int) 中所示),然后给定您的 operator/ ,以下内容是不明确

// ambiguous: operator/(int, int) (built-in) or
//            operator/(distance const&, field_type) ?
31 / month;

的,也许最好使用适当的运算符使 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):

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.

≈。彩虹 2024-08-31 16:09:15

如果您问此代码是否合法:

enum A {
    x,y
};

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

不幸的是,答案是“是”。存在从枚举值到整数的隐式转换。

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.

魄砕の薆 2024-08-31 16:09:15

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

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

瞎闹 2024-08-31 16:09:15

嗯,关于day * 3的问题的答案是:是的,你可以做到。为此,您不需要任何运算符重载。结果将是6。但是,这可以通过将 day 常量转换为 int 类型、在 int 类型内执行乘法并给出 类型的结果来实现。 int,即6是一个int。这就提出了下一个问题:你同意它是一个 int 吗?之后您打算如何处理6?如果 int 适合您的目的,那么您不需要执行任何操作。

但是,有可能您实际上想要获取 day * 3field_type 类型的结果。您会看到,在 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 转换为枚举类型,则结果是未指定的(尽管在实践中它通常会“按预期”工作)。

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文