方便地为枚举定义位运算符以创建位标志

时间:2016-03-07 19:28:06

标签: c++ enums

为了定义要用作位标志的枚举,可以使用适当的值定义枚举本身,并为枚举类型定义位运算符,如下所示。

enum ENUM_TYPE
{
    ET_VAL1    = 1L << 0,
    ET_VAL2    = 1L << 1
}

inline ENUM_TYPE operator& (ENUM_TYPE _a, ENUM_TYPE _b) 
{return ENUM_TYPE(static_cast<int>(_a) & static_cast<int>(_b));}

/* similarly for |, ^, ~, |=, &=, ^= */

问题在于,按位运算符的定义占用了大量空间,使代码难以阅读,并且编写起来很烦人,特别是如果定义了各种枚举。

可以在头文件中创建一个模板,如下所示,并在必要时简单地包含该模板。然而,这会引入在类型上使用按位运算符的风险,但没有明确定义它们。

template<typename ENUM_T>
inline ENUM_T operator& (ENUM_T _a, ENUM_T _b) 
{return ENUM_T(static_cast<int>(_a) & static_cast<int>(_b));}

还可以创建宏,如下所示。这似乎容易出错?

#define BITWISE_AND(TYPE) inline TYPE operator& (TYPE _a, TYPE _b)\
        {return TYPE(static_cast<int>(_a) & static_cast<int>(_b));}

#define BITWISE_ALL(TYPE) BITWISE_AND(TYPE) /* and others */

什么是&#34;正确&#34;做上述方法?各种标志定义是代码味道吗?通常在生产代码中做什么?

3 个答案:

答案 0 :(得分:1)

不是您问题的直接答案,但您是否考虑过使用std::bitset<N>?我发现定义和使用标志是一种方便的方法。例如:

#include <iostream>
#include <bitset>


using Flag = std::bitset<3>;

const Flag FOO("001");
const Flag BAR("010");
const Flag BAZ("100");

int main() {

  Flag thing("011");

  if((thing & FOO) == FOO) {
    std::cout << "thing has foo\n";
  } else {
    std::cout << "thing does not have foo\n";
  }

  if((thing & BAR) == BAR) {
    std::cout << "thing has bar\n";
  } else {
    std::cout << "thing does not have bar\n";
  }


  if((thing & BAZ) == BAZ) {
    std::cout << "thing has baz\n";
  } else {
    std::cout << "thing does not have baz\n";
  }


}

示例输出:

$ g++ example.cpp -std=c++14 -Wall -Wextra
$ ./a.out
thing has foo
thing has bar
thing does not have baz

对于more information on std::bitset<N> in cppreference.com,其描述为:

  

类模板bitset表示N位的固定大小序列。   位组可以由标准逻辑运算符操作并进行转换   来往于字符串和整数。

答案 1 :(得分:0)

你可以创建一个bool数组并将它放在一个struct中,使得最终的struct&#39; typesafe&#39;,如果你在C ++中工作,可以设置和修改方法。

答案 2 :(得分:0)

如果您打算重新定义运营商,为什么不使用有意义的运营商呢?当你真的想说“ET_VAL2 &”时,按位运算符毫无意义。同样,测试要设置的标志应该通过比较运算符IMO进行。 flags是需要完成的逻辑操作,但“ET_VAL1 LIKE "%term%"”看起来不像是一个测试。

有关我定义位标志集的方法,请参阅我对这个问题的回答:https://stackoverflow.com/a/41516273/7328782