【问题标题】:How to reuse enum operator overloads in C++?如何在 C++ 中重用枚举运算符重载?
【发布时间】:2010-06-22 12:13:27
【问题描述】:

我在 C++ 中有几个类似标志的枚举。例如:

enum some_state {
  state_normal        = 1 << 0,
  state_special       = 1 << 1,
  state_somethingelse = 1 << 2,
  state_none          = 0,
};
some_state var1;

现在在使用&amp;| 之类的位运算符时,我会遇到编译器错误。我知道我可以超载operator | et.al。对于枚举,但我讨厌为每个枚举再次这样做。有没有重用运算符重载的好方法?

【问题讨论】:

标签: c++ enums operator-overloading


【解决方案1】:
enum some_state {
  state_normal        = 1 << 0,
  state_special       = 1 << 1,
  state_somethingelse = 1 << 2,
  state_none          = 0,
};

int main() {
    some_state var1 = state_normal;
    some_state var2 = state_special;
    unsigned int var3 = var1 | var2;
}

对我来说很好用。不重载就不能使用|,&等的原因是编译器不能保证var1 |的结果。 var2 是枚举中的有效值。如果要采用移位标志,则需要采用整数类型,而不是枚举类型。这在 Direct3D 等专业头文件中一直使用。

【讨论】:

  • 感谢您的解释。我认为编译器永远不能保证 var1 | 的结果var2 是枚举中的有效值,因为 var1 和 var2 可以包含任何值。为了便于阅读,我也想将 var3 声明为 some_state,这就是我需要运算符重载的原因。此外,#define 将枚举“注释”为包含标志。
【解决方案2】:

我尝试并搜索,我认为最好的解决方案是#define。基于something I found

#define FLAGS(T) \
inline T  operator  |(const T s, const T e) { return (T)((unsigned)s | e); } \
inline T &operator |=(T      &s, const T e) { return s = s | e; }            \
inline T  operator  &(const T s, const T e) { return (T)((unsigned)s & e); } \
inline T &operator &=(T      &s, const T e) { return s = s & e; }            \
inline T  operator  ^(const T s, const T e) { return (T)((unsigned)s ^ e); } \
inline T &operator ^=(T      &s, const T e) { return s = s ^ e; }            \
inline T  operator  ~(const T s)            { return (T)~(unsigned)s; }

这可以像这样使用:

enum some_state {
  state_normal        = 1 << 0,
  state_special       = 1 << 1,
  state_somethingelse = 1 << 2,
  state_none          = 0,
};
FLAGS(some_state)

some_state var1;

对于 Visual Studio,可能需要这样来消除一些警告:

#pragma warning(disable: 4505) // '*' : unreferenced local function has been removed

事实上,Windows SDK 有the DEFINE_ENUM_FLAG_OPERATORS macro 可以做到这一点。


另一种方法是包装类like DEF_ENUM_FLAGS_TYPE uses

或者使用the LLVM_MARK_AS_BITMASK_ENUM macro 之类的东西。不过,您可能需要最新的编译器。

【讨论】:

  • 很好,您回答了自己的问题! :)
  • 如果你真的想这样做, inline 而不是 static 对链接器有更好的语义 - 大致来说,static 意味着它在这个文件中使用,并且只在这个文件中,inline 意味着它可以在多个文件中定义。
  • @Akanksh:你有反对意见吗?
  • 哦不,很抱歉,如果有这种感觉,我只是非常尊重那些试图自己寻找解决方案的人,而不是仅仅把它放在这里等待回复。我的最后评论是最好的方式,如果看起来不是这样,我深表歉意。
  • 我现在正在使用您的建议。如果这真的是实现它的唯一方法,那么我认为它是 C++ 中不一致的enum class 实现
【解决方案3】:

使用现有的模板库(例如 bitwise-enum)来提供操作,而不是自己编写。

【讨论】:

  • 它是 GPL,所以我不能在我们的商业程序中使用它。抱歉,不清楚。
  • 为枚举编写包装类(枚举数组作为索引,位作为值)相当简单,而且肯定比使用原始枚举更安全(和优雅)。
猜你喜欢
  • 2017-12-28
  • 2010-11-24
  • 1970-01-01
  • 2023-03-18
  • 1970-01-01
  • 2011-02-04
  • 1970-01-01
  • 1970-01-01
  • 2013-03-31
相关资源
最近更新 更多