嗯,有简单的方法和丑陋的方法。
简单的方法是将这些位定义为与存在不重叠,例如:
enum E
{
a = 1 << 0,
b = 1 << 1,
c = 1 << 2,
total = 1 << 3 // or a | b | c, not sure what the intent was
};
丑陋的方式:
#define MAKEA(x) (new A((E_helper() | x).get()))
whereE_helper
是一个覆盖operator|(enum E)
.
class E_helper
{
unsigned accum;
public:
explicit E_helper(unsigned initial = 0) : accum(initial) {}
unsigned get() const { return accum; }
E_helper operator|(enum E e) const { return E_helper(accum | (1 << (unsigned)e)); }
};
然后你的用户可以说
A* p = MAKEA(a | c);
扩展到
A* p = (new A((A_helper() | a | c).get());
这导致了这一系列事件
A_helper.operator|(a).operator|(c).get()
更好的是,将.get()
调用移动到 A 的构造函数中,然后它接受一个类型为 的参数A_helper
。这将让您捕捉到用户忘记使用MAKEA
宏的情况。
但是请注意,丑陋的方式会暴露出违反直觉的行为。例如,A* p = MAKEA(a | c);
不同于A* p = MAKEA( (a | c) );
和char mask = a | c; A* p = MAKEA(mask);