有没有一种方法可以为枚举类型定义operator=运算符?

3

我有一个枚举,但我想为它添加一个赋值运算符,以便能够分配一个不属于原始枚举的类型。例如:

enum class X : int
{
  A, B, C, D
}

enum class Y : char
{
  A, B, C, D
}

Y& operator=(Y& lhs, X rhs)
{
  return Y = static_cast<Y>(X);
}

但是我得到了一个 'operator ='必须是非静态成员 的错误。有没有办法解决这个问题?


我无法想象这个的好用途。你能帮我吗? - Lightness Races in Orbit
@BarryTheHatchet,这是因为我正在尝试更新一些过时的代码。他们在两个不同的位置使用相同的常量,但在其中一个位置,它的大小为1字节,在另一个位置,它的大小为2字节。我宁愿不更改结构的二进制兼容性,以防止出现任何问题。 - Adrian
如果您将原始代码称为过时的,我猜它没有使用enum class,我猜这是您进行的修改。是这样吗?如果是这样,那么是否接受一些不使用enum class的替代方案呢? - user743382
@hvd,它使用的是intchar,甚至没有枚举。 - Adrian
1
那么Brian的答案正是我想要发表的。如果我是你,我会放弃使用enum class,因为你可以不使用它来达到你想要的效果。 - user743382
显示剩余4条评论
3个回答

9
你做不到,因为错误消息告诉你,operator=只能是非静态成员函数,而枚举类型不能有成员。如果你真的想要从不同的枚举类型中进行赋值,也许你应该把Y变成一个类。另一种可能性是编写帮助函数来执行赋值操作。

唔,这真是不幸。:( 把 Y 变成一个类可能会在类型方面带来更多麻烦... - Adrian
1
@Adrian 打字不是问题。隐藏的逻辑错误才是问题。隐式转换会隐藏微妙的逻辑错误。 - Richard Hodges
通过输入麻烦,我指的是每个枚举类型(类和枚举)都有两种类型,其中枚举类型位于第二级。这也许不是很糟糕,但很烦人。class ByteX { enum X { A, ... }; }; class WordX { enum X { A, ... }; }; class DWordX { enum X { A, ... }; }; void fn() { DWordX x = WordX::X::A; }. 或者我想它们都可以引用Byte的那个,或者将Byte枚举定义为外部枚举... - Adrian

3

枚举类是一种繁琐的结构,您可以避免使用。只需将旧的枚举包装在一个结构体中:

#include <iostream>

struct X
{
  enum enum_type { A, B, C, D };
  typedef int value_type;
  value_type value;

  X(enum_type value) : value(value) {}
  operator enum_type () const { return static_cast<enum_type>(value); }
};

struct Y
{
  enum enum_type { A, B, C, D };
  typedef char value_type;
  value_type value;

  Y(enum_type value) : value(value) {}
  operator enum_type () const { return static_cast<enum_type>(value); }

  Y& operator = (X rhs) {
    value = rhs;
    return *this;
  }
};

int main()
{
    X x = X::A;
    Y y = Y::B;
    std::cout << y << '\n';
    y = x;
    std::cout << y << '\n';
}

1
不要鼓励使用hack而不是清晰的解决方案。如果你想要作用域枚举,那么枚举类正是你所需要的。编写一个辅助函数,这是一种较小的hack。 - szali

0
你可以编写一个转换函数而不是一个转换运算符。无论如何,这种方式更好,因为它在调用时清晰地表达了意图。
enum class X : int
{
    A, B, C, D
};

enum class Y : char
{
    A, B, C, D
};

Y to_y(X rhs)
{
    auto as_int = static_cast<int>(rhs);  // allowed
    auto as_char = static_cast<char>(as_int); // allowed if the int is known to fit
    return static_cast<Y>(as_char); // allowed if the char is known to be the right value
}

int main()
{
    auto x = X::C;

    auto y = to_y(x);

    return 0;
}

谢谢,但我希望它是隐式的,因为它将到处存在。 - Adrian
如果它将无处不在,你绝对不希望它是隐含的。 - Richard Hodges
是的,我同意。转换仅限于从类型 X 到类型 Y,然后再返回。它们表示相同的信息,但大小不同。它们永远不会互相溢出。没有任何理由不将其视为隐式转换。 - Adrian
不,我不想进行隐式转换为数字类型,只想转换为我指定的类型。 - Adrian
所以使用旧式的class,带有转换和赋值运算符。 - Spencer
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接