为了定义要用作位标志的枚举,可以使用适当的值定义枚举本身,并为枚举类型定义位运算符,如下所示。
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;做上述方法?各种标志定义是代码味道吗?通常在生产代码中做什么?
答案 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