Como (con suerte) todos sabemos, vector<bool>
está totalmente roto y no se puede tratar como una matriz C. ¿Cuál es la mejor forma de obtener esta funcionalidad? Hasta ahora, las ideas en las que he pensado son:
- Utilice a
vector<char>
en su lugar, o - Use una clase contenedora y tenga
vector<bool_wrapper>
¿Cómo manejan ustedes este problema? Necesito la c_array()
funcionalidad.
Como pregunta paralela, si no necesito el c_array()
método, ¿cuál es la mejor manera de abordar este problema si necesito acceso aleatorio? ¿Debería usar un deque o algo más?
Editar:
- Necesito un tamaño dinámico.
- Para los que no lo saben,
vector<bool>
está especializado para que cadabool
tome 1 bit. Por lo tanto, no puede convertirlo en una matriz de estilo C. - Supongo que "envoltorio" es un nombre poco apropiado. Estaba pensando en algo como esto:
Por supuesto, entonces tengo que leer un my_bool
debido a posibles problemas de alineación :(
struct my_bool
{
bool the_bool;
};
vector<my_bool> haha_i_tricked_you;
vector<bool>
solo causé un error de carrera de datos en mi código, ya que esperaba que diferentes subprocesos pudieran modificar diferentes elementos en el vector al mismo tiempo de manera segura. Resuelto usandodeque<bool>
.Respuestas:
Úselo
std::deque
si no necesita la matriz, sí.De lo contrario, use una alternativa en la
vector
que no se especialicebool
, como la de Boost Container .fuente
Ese es un problema interesante.
Si necesita lo que hubiera sido un std :: vector si no estuviera especializado, entonces tal vez algo así funcionaría bien con su caso:
#include <vector> #include <iostream> #include <algorithm> class Bool { public: Bool(): m_value(){} Bool( bool value ) : m_value(value){} operator bool() const { return m_value; } // the following operators are to allow bool* b = &v[0]; (v is a vector here). bool* operator& () { return &m_value; } const bool* operator& () const { return &m_value; } private: bool m_value; }; int main() { std::vector<Bool> working_solution(10, false); working_solution[5] = true; working_solution[7] = true; for( int i = 0; i < working_solution.size(); ++i ) { std::cout<< "Id " << i << " = " << working_solution[i] << "(" <<(working_solution[i] ? "true" : "false") << ")" <<std::endl; // i used ? : to be sure the boolean evaluation is correct } std::sort( working_solution.begin(), working_solution.end()); std::cout<< "--- SORTED! ---" << std::endl; for( int i = 0; i < working_solution.size(); ++i ) { bool* b = &working_solution[i]; // this works! std::cout<< "Id " << i << " = " << working_solution[i] << "(" << (working_solution[i] ? "true" : "false") << ")" <<std::endl; // i used ? : to be sure the boolean evaluation is correct } std::cin.get(); return 0; }
Intenté esto con VC9 y parece funcionar bien. La idea de la clase Bool es simular el tipo bool proporcionando el mismo comportamiento y tamaño (pero no el mismo tipo). Casi todo el trabajo lo realiza el operador bool y los constructores de copia predeterminados aquí. Agregué un tipo para asegurarme de que reacciona como se supone cuando se usan algoritmos.
No estoy seguro de que se adapte a todos los casos. Si es adecuado para sus necesidades, sería menos trabajo que reescribir una clase similar a un vector ...
fuente
sizeof(bool)
no es obligatorio1
"operator bool() const
aoperator bool&()
. Esto hace que refleje mejor el comportamiento de un bool simple, ya que admite asignaciones, etc.en casos en losv[0] = true;
que realmente no puedo ver un problema con este cambio, ¿puedo hacer la edición?Depende de tus necesidades. Yo iría por cualquiera
std::vector<unsigned char>
. Escribir un contenedor puede estar bien si solo usa un subconjunto de la funcionalidad, de lo contrario se convertirá en una pesadilla.fuente
unsigned char
es siempre de un solo byte, aunque esuint8_t
posible que la implementación no lo admita.uint_fast8_t
aunque podría funcionar si la intención es dejar claro que es un solo byte y no un personaje, sino que también podría usarstd::byte
entoncesboost::container::vector<bool>
:fuente
Considere usar un vector <int>. Una vez que pasa la compilación y la verificación de tipos, bool e int son solo palabras de máquina (editar: aparentemente esto no siempre es cierto; pero será cierto en muchas arquitecturas de PC). En aquellos casos en los que desee realizar una conversión sin una advertencia, utilice "bool foo = !! bar", que convierte cero en falso y no cero en verdadero.
Un vector <char> o similar usará menos espacio, aunque también tiene el potencial de recibir un golpe de velocidad (muy pequeño) en algunas circunstancias, porque los caracteres son menores que el tamaño de la palabra de la máquina. Esta es, creo, la razón principal por la que los bools se implementan usando ints en lugar de chars.
Si realmente quieres una semántica limpia, también me gusta la sugerencia de crear tu propia clase booleana: parece un bool, actúa como un bool, pero engaña a la especialización de la plantilla.
Además, bienvenido al club de personas que desean eliminar la especialización vector <bool> del estándar C ++ (con bit_vector para reemplazarla). Es donde pasan el rato todos los niños geniales :).
fuente
Este problema ya se discutió en comp.lang.c ++. Moderated. Soluciones propuestas:
std::allocator
) y su propia especialización vectorial;std::deque
(como antes se recomendó en uno de los libros de S. Mayers), pero esto no es para sus requisitos;bool
envoltura de POD ;char
/int
/ etc) con el mismo tamaño que en subool
lugarbool
;También temprano vi una propuesta para el comité estándar: introducir macro (algo como
STD_VECTOR_BOOL_SPECIAL
) para no permitir esta especialización, pero AFAIK, esta propuesta no se implementó en implementaciones stl y no fue aprobada.Parece que su problema no tiene forma de hacer esto bien ... Quizás en C ++ 0x.
fuente
La respuesta más simple es usar
vector<struct sb>
wheresb
isstruct {boolean b};
. Entonces puedes decirpush_back({true})
. Parece bien.fuente
Mi solución alternativa preferida es una
vector
enumeración de ámbito que tiene un tipo subyacente debool
. Esto se acerca bastante alvector<bool>
que hubiéramos tenido si el comité no lo hubiera especializado.enum class switch_status : bool { ON, OFF }; static_assert( sizeof( switch_status ) == 1 ); ::std::vector<switch_status> switches( 20, switch_status::ON ); static_assert( ::std::is_same_v< decltype( switches.front() ), switch_status &> ); static_assert( ::std::is_same_v< decltype( switches.back() ), switch_status &> ); static_assert( ::std::is_same_v< decltype( switches[ 0 ] ), switch_status &> );
Tendrás tus propias opiniones sobre la sabiduría de abrazar yesos hacia / desde
bool
:enum class switch_status : bool { OFF = false, ON = true }; static_assert( static_cast< bool >( switch_status::ON ) == true ); static_assert( static_cast< bool >( switch_status::OFF ) == false ); static_assert( static_cast< switch_status >( true ) == switch_status::ON ); static_assert( static_cast< switch_status >( false ) == switch_status::OFF );
fuente