代码之家  ›  专栏  ›  技术社区  ›  Michel de Ruiter

如何在C++中重用枚举运算符重载?

  •  1
  • Michel de Ruiter  · 技术社区  · 14 年前

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

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

    现在开始使用位运算符,比如 & | ,我得到编译器错误。我知道我可以超载 operator | 等。对于枚举,但我不愿意为每一个枚举再次这样做。是否有一种重用运算符重载的好方法?

    3 回复  |  直到 8 年前
        1
  •  5
  •   Puppy    14 年前
    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这样的专业头文件中一直使用。

        2
  •  3
  •   Michel de Ruiter    8 年前

    我尝试过并搜索过,我认为最好的解决方案是定义。基于 我找到的东西

    定义标志(t)\ 内联t运算符(const t s,const t e)返回(t)((无符号)s e);\ 内联t&operator=(t&s,const t e)返回s=s e;\ 内联t运算符&(const t s,const t e)返回(t)((无符号)s&e);\ 内联t&operator&=(t&s,const t e)返回s=s&e;\ 内联t运算符^(const t s,const t e)返回(t)((无符号)s^e);\ 内联t&operator^=(t&s,const t t e)返回s=s^e;\ 内联t运算符~(const t s)返回(t)~(无符号)s; < /代码>

    这可以像这样使用:

    枚举一些\u状态{
    状态“正常”=1<<0,
    州特殊=1<<1,
    状态“somethingelse=1<<2,
    状态“无”=0,
    };
    标志(某些状态)
    
    一些状态变量1;
    < /代码> 
    
    

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

    pragma warning(disable:4505)//'*':unreferenced local function has been removed
    < /代码> 
    
    

    事实上,Windows SDK具有Thedefine_enum_flag_operatorsmacroto do just that.


    另一种方法是包装类likedef_enum_flags_type.>code>uses.>a>。

    或者使用类似不过,您可能需要最新的编译器。

    我发现的东西:

    #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 SDKthe DEFINE_ENUM_FLAG_OPERATORS macro就这么做。


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

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

        3
  •  2
  •   Pete Kirkham    14 年前

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