Usando banderas binarias para representar estados, opciones, etc.
Pregunta
Si quisiera representar estados u opciones o algo similar usando binarios " flags " para poder pasarlos y almacenarlos en un objeto como OPTION1 | OPTION2
donde OPTION1
es 0001 y OPTION2
es 0010, de modo que lo que se pasa es 0011, que representa una combinación de las opciones.
¿Cómo haría esto en C ++? Estaba pensando en algo como
enum Option {
Option_1 = 0x01,
Option_2 = 0x02,
Option_3 = 0x04,
//...
}
void doSomething(Option options) {
//...
}
int main() {
doSomething(Option_1|Option_2);
}
Pero idealmente, doSomething
sabe cómo interpretar la Opción dada.
¿Estoy en el camino correcto? ¿Hay alguna manera mejor?
Actualizar
¿Y no tendría que definir también una Option
para cada combinación posible?
Solución
Esta es una forma común en que se hacen estas cosas. doSomething
puede usar el operador bitcode y
para ver si una opción está seleccionada:
if (options & Option_1){
// option 1 is selected
}
Como alternativa, puede considerar el uso de campos de bits :
struct Options {
unsigned char Option_1 : 1;
unsigned char Option_2 : 1;
};
Options o;
o.Option_1 = 1;
o.Option_2 = 0;
Otros consejos
Esa sería la forma en que lo haría. Sin embargo, hay muchos trucos que puedes usar para hacer que la enumeración sea un poco más legible:
enum Option {
Option1 = 1 /*<< 0*/,
Option2 = 1 << 1,
Option3 = 1 << 2,
// etc.
};
Además, deberá especificar operadores bitwise para su enumeración. Considere algo como las utilidades enum_ops
de ASL para ayudar con esto.
Vale la pena señalar que la forma en que las personas suelen usar estos indicadores es definir la función de la siguiente manera:
void doSomething( unsigned int options )
{
//...
}
todo lo demás funcionará exactamente como quieres :)
La otra forma es crear su propio " Banderas " clase. Luego tienes un par de funciones como las siguientes en la clase:
bool GetOption( Option option )
{
return (m_Option & option) > 0;
}
void SetOption( Option option )
{
m_Option |= option;
}
void ClearOption( Option option )
{
m_Option &= ~option;
}
o incluso sobrecargue a los operadores para que hagan exactamente lo que le gustaría, por ejemplo:
Flags( unsigned int options ) :
m_Option( options )
{
}
Flags operator|( const Flags& flags )
{
return Flags( m_Option | flags.m_Option );
}
y así sucesivamente.
Es posible que desee consultar stl bitset . Algunas personas predicarían que siempre deberías usar esos en lugar de bitflags estilo C. Sin embargo, ambas soluciones son buenas de la OMI.