Tengo un conjunto de banderas de bits que se usan en un programa que transfiero de C a C++.¿Por qué C++ admite la asignación hexadecimal, pero carece de asignación binaria? ¿Cuál es la mejor manera de almacenar banderas?
Para empezar ...
Las banderas en mi programa se definieron previamente como:
/* Define feature flags for this DCD file */
#define DCD_IS_CHARMM 0x01
#define DCD_HAS_4DIMS 0x02
#define DCD_HAS_EXTRA_BLOCK 0x04
... Ahora he entendido que #defines para las constantes (en comparación con las constantes de clase, etc.) generalmente se consideran malas formas.
Esto plantea preguntas sobre cómo almacenar banderas de bits en C++ y por qué C++ no admite la asignación de texto binario a un int, como permite asignar números hexadecimales de esta manera (a través de "0x"). Estas preguntas se resumen al final de esta publicación.
pude ver una solución sencilla es simplemente crear constantes individuales:
namespace DCD {
const unsigned int IS_CHARMM = 1;
const unsigned int HAS_4DIMS = 2;
const unsigned int HAS_EXTRA_BLOCK = 4;
};
Vamos a llamar a esta idea 1.
Otra idea que tenía era utilizar una enumeración entero:
namespace DCD {
enum e_Feature_Flags {
IS_CHARMM = 1,
HAS_4DIMS = 2,
HAS_EXTRA_BLOCK = 8
};
};
Pero una cosa que me molesta acerca de esto es que es menos intuitivo cuando se trata de valores más altos, parece ... es decir,
namespace DCD {
enum e_Feature_Flags {
IS_CHARMM = 1,
HAS_4DIMS = 2,
HAS_EXTRA_BLOCK = 8,
NEW_FLAG = 16,
NEW_FLAG_2 = 32,
NEW_FLAG_3 = 64,
NEW_FLAG_4 = 128
};
};
Vamos a llamar a esta opción enfoque 2.
estoy considerando el uso de solución de macro de Tom Torf:
#define B8(x) ((int) B8_(0x##x))
#define B8_(x) \
(((x) & 0xF0000000) >(28 - 7) \
| ((x) & 0x0F000000) >(24 - 6) \
| ((x) & 0x00F00000) >(20 - 5) \
| ((x) & 0x000F0000) >(16 - 4) \
| ((x) & 0x0000F000) >(12 - 3) \
| ((x) & 0x00000F00) >(8 - 2) \
| ((x) & 0x000000F0) >(4 - 1) \
| ((x) & 0x0000000F) >(0 - 0))
convertir en funciones inline, por ejemplo
#include <iostream>
#include <string>
....
/* TAKEN FROM THE C++ LITE FAQ [39.2]... */
class BadConversion : public std::runtime_error {
public:
BadConversion(std::string const& s)
: std::runtime_error(s)
{ }
};
inline double convertToUI(std::string const& s)
{
std::istringstream i(s);
unsigned int x;
if (!(i >> x))
throw BadConversion("convertToUI(\"" + s + "\")");
return x;
}
/** END CODE **/
inline unsigned int B8(std::string x) {
unsigned int my_val = convertToUI(x.insert(0,"0x").c_str());
return ((my_val) & 0xF0000000) >(28 - 7) |
((my_val) & 0x0F000000) >(24 - 6) |
((my_val) & 0x00F00000) >(20 - 5) |
((my_val) & 0x000F0000) >(16 - 4) |
((my_val) & 0x0000F000) >(12 - 3) |
((my_val) & 0x00000F00) >(8 - 2) |
((my_val) & 0x000000F0) >(4 - 1) |
((my_val) & 0x0000000F) >(0 - 0);
}
namespace DCD {
enum e_Feature_Flags {
IS_CHARMM = B8("00000001"),
HAS_4DIMS = B8("00000010"),
HAS_EXTRA_BLOCK = B8("00000100"),
NEW_FLAG = B8("00001000"),
NEW_FLAG_2 = B8("00010000"),
NEW_FLAG_3 = B8("00100000"),
NEW_FLAG_4 = B8("01000000")
};
};
¿Es esto una locura? ¿O parece más intuitivo? Vamos a llamar a esta elección 3.
Así que para recapitular, mis preguntas sobre-arqueo son:
1. ¿Por qué no C++ soportan una "0b" bandera valor, similar a "0 x"?
2. ¿Cuál es el mejor estilo para definir indicadores ...
i. Constantes envueltas en espacio de nombres.
ii. Espacio de nombres envuelto enum de entradas sin firmar asignadas directamente.
iii. Espacio de nombres envuelto enum de ints sin signo asignados mediante una cadena binaria legible.
¡Gracias de antemano! Y por favor no cierre este hilo como algo subjetivo, porque realmente quiero obtener ayuda sobre cuál es el mejor estilo y por qué C++ carece de la capacidad de asignación binaria incorporada.
EDITAR 1
Un poco de información adicional. Leeré un bitfield de 32 bits de un archivo y luego lo probaré con estos indicadores. Así que tenlo en cuenta cuando publiques sugerencias.
Quiere decir 'inline unsigned int bit (n) {1 << (n);}' right? ;) –
@Jason: No; los inicializadores del enumerador deben ser expresiones constantes; no puede llamar a una función en una expresión constante, por lo que tiene que ser una macro. –
hrmm ... Supongo que es un buen momento para usar una macro? –