函数的模式,可以采用枚举值或枚举值的组合

时间:2012-10-25 19:55:01

标签: c++ enums bit-manipulation

让我说我有这个:

enum E{ 
a,
b,
c,
total
}

class A {
char mask; // supposed to contains combinations of values of the enum, like a or c, etc
}

是否有一个体面的解决方案以用户友好的方式构建对象A? 例如,我可以这样做:

A(E e) {
mask = 1 << e;
}

但这只有在你想要只用枚举的1个元素制作掩码时才有效 理想情况下,用户可以执行以下操作:

A* a = new A(a | c)

这会自动创建

mask = 1 << a | 1 << c;

有关如何正确执行此操作的任何想法? 感谢

修改

遗憾的是,我无法控制初始枚举,并且值逐渐增加1

4 个答案:

答案 0 :(得分:1)

嗯,有简单的方法和丑陋的方式。

简单的方法是将比特定义为不重叠,例如:

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()))

其中E_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()

更好的是,在A的构造函数中移动.get()调用,然后获取类型为A_helper的参数。这将让您了解用户忘记使用MAKEA宏的情况。

然而,请注意,丑陋的方式暴露了反直觉的行为。例如,A* p = MAKEA(a | c);A* p = MAKEA( (a | c) );char mask = a | c; A* p = MAKEA(mask);

不同

答案 1 :(得分:1)

为了维护类型并为按位|&^提供支持,我在宏中编写以下运算符,并且通常在我的项目中的枚举类型中使用它们:

enum E {
    a = 1 << 0,
    b = 1 << 1,
    c = 1 << 2,
    total = a | b | c
};
E operator | (E lhs, E rhs ) {
    return static_cast<E>( static_cast<int>(lhs) | static_cast<int>(rhs) );
}
E operator & (E lhs, E rhs ) {
    return static_cast<E>( static_cast<int>(lhs) & static_cast<int>(rhs) );
}
E operator ^ (E lhs, E rhs ) {
    return static_cast<E>( static_cast<int>(lhs) ^ static_cast<int>(rhs) );
}
E operator ~ (E e ) {
    return static_cast<E>( ~static_cast<int>(e) );
}
E& operator |= (E& lhs, E rhs ) {
    return lhs = static_cast<E>( static_cast<int>(lhs) | static_cast<int>(rhs) );
}
E& operator &= (E& lhs, E rhs ) {
    return lhs = static_cast<E>( static_cast<int>(lhs) & static_cast<int>(rhs) );
}
E& operator ^= (E& lhs, E rhs ) {
    return lhs = static_cast<E>( static_cast<int>(lhs) ^ static_cast<int>(rhs) );
}

现在你可能有:

void test( E e );
test( a | b );
E e = c;
e |= b;
e = e & d;
e ^= a;
e = ~e;

答案 2 :(得分:0)

尝试

enum E{ 
a = 1,
b = 2,
c = 4,

}

然后

A var(a | c)

将起作用

然后检查是否(例如)a设置为&,即if (mask & a) ...

答案 3 :(得分:0)

您需要从一组连续值生成位掩码。这很简单:

int mask(E e) {
    return 1 << e;
}

现在你可以或掩码值一起调用你的函数:

A var(mask(a) | mask(b));