2009-03-22 12 views
77

Como (afortunadamente) todos sabemos, vector<bool> está totalmente roto y no puede tratarse como una matriz c. ¿Cuál es la mejor manera de obtener esta funcionalidad? Hasta el momento, las ideas que he pensado son:Alternativa al vector <bool>

  • vector<char> Utilice un lugar, o
  • Utilice un contenedor de clase y tienen vector<bool_wrapper>

¿Cómo ustedes manejar este problema? Necesito la funcionalidad c_array().

Como una pregunta complementaria, si no necesito el método c_array(), ¿cuál es la mejor manera de abordar este problema si necesito acceso aleatorio? ¿Debería usar un deque u otra cosa?

Editar:

  • sí necesito ajuste dinámico del tamaño.
  • Para aquellos que no saben, vector<bool> está especializado de modo que cada bool toma 1 bit. Por lo tanto, no puede convertirlo a 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 en un my_bool debido a posibles problemas de alineación :(

struct my_bool 
{ 
    bool the_bool; 
}; 
vector<my_bool> haha_i_tricked_you; 
+2

¿Hay alguna razón para no usar ... una matriz estilo C? – kquinn

+0

rlbond, ¿necesitas tamaño dinámico? –

+14

Ok Voy a morder: ¿por qué crees que el vector está "totalmente roto"? –

Respuesta

35

Uso std::deque si usted no necesita la matriz, sí .

de lo contrario usar una alternativa vector que no se especializa en bool, tales como el de Boost Container.

+1

¿Por qué no usas 'boost :: container :: vector' que funciona para' bool' como se espera? – gnzlbg

+1

@gnzlbg - good llame, he actualizado la respuesta (¡la publiqué durante dos años antes de que se agregara el Contenedor a Boost!) –

14

depende de sus necesidades. I w podría ir para std::vector<unsigned char>. Escribir un contenedor puede estar bien si solo usa un subconjunto de la funcionalidad, sino se convertirá en una pesadilla.

20

Eso es un problema interesante.

Si necesita lo que habría sido un std :: vector si no era especializado, entonces tal vez algo por el estilo que funciona 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 * const 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; 
} 

He intentado esto con VC9 y parece trabaja bien. La idea de la clase Bool es simular el tipo bool al proporcionar el mismo comportamiento y tamaño (pero no del mismo tipo). Casi todo el trabajo lo realiza el operador bool y los constructores de copia predeterminados aquí. Agregué una clasificación para asegurarme de que reacciona como se supone al usar algoritmos.

No estoy seguro de que sea adecuado para todos los casos. Si es adecuado para sus necesidades, sería menos trabajo que reescribir una clase similar a un vector ...

+0

solución no completa, no puede escribir algo como: bool * b = &v[0]; – bayda

+0

Correcto, solo puede reinterpretarlo. – Klaim

+2

como solución podríamos agregar bool * operator &() {return & m_value; } y conversión a const bool *, bool & y const bool &. Pero de todos modos, la idea principal es correcta. – bayda

4

este problema ya fue discutido en comp.lang.C++.moderados (http://groups.google.ru/group/comp.lang.c++.moderated/browse_thread/thread/b8d6dd59dfb295c0/e23e0f606d64550a)
soluciones propuestas:

  • su propio asignador (basados ​​en std :: asignador) y la propia especialización del vector;
  • use std :: deque (como se recomendó anteriormente en uno de los libros de S. Mayers) - pero esto no es para sus requisitos;
  • make POD bool wrapper;
  • utiliza algo (char/int/etc) con el mismo tamaño que bool bool en su lugar;

también temprano vi propuesta de norma commitette - introducir macro (algo así como STD_VECTOR_BOOL_SPECIAL) para dissallow esta especialización - que yo sepa, pero esta propuesta no se puso en práctica en implementaciones stl y no se approoved.

parece que su problema no tiene maneras de hacer esto muy bien .. tal vez en C++ 0x

5

considerar el uso de un vector < int>. Una vez que superas la compilación y la verificación de tipos, bool e int son palabras simples (edición: aparentemente esto no siempre es cierto, pero será cierto en muchas arquitecturas de PC). En los casos en que desee convertir sin advertencia, use "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 dar un golpe de velocidad (muy pequeño) en algunas circunstancias, porque los caracteres son menores que el tamaño de palabra de la máquina. Esta es, creo, la razón principal por la que los bools se implementan usando ints en lugar de caracteres.

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, bienvenidos al club de personas que quieren el vector < bool> especialización eliminada del estándar C++ (con bit_vector para reemplazarlo). Es donde todos los chicos cool pasan el rato :).

+5

bool e int no son necesariamente palabras de máquina. En el sistema que desarrollo para, sizeof (bool) = 1 y sizeof (int) = 4. Los requisitos de alineación y las instrucciones de carga/almacenamiento generadas difieren en forma correspondiente. – leander

10

¿Cómo manejan este problema? Necesito la funcionalidad c_array().

boost::container::vector<bool>:

vector < bool> especialización ha sido bastante problemático, y ha habido varios intentos infructuosos para despreciar o eliminarlo de la norma. Boost.Container no lo implementa ya que hay una solución superior Boost.DynamicBitset.

...

Así impulso :: contenedor :: vector :: iterador devuelve referencias reales bool y funciona como un contenedor totalmente compatible. Si necesita una versión optimizada de memoria de boost :: container :: vector < bool> funcionalidades, utilice Boost.DynamicBitset.

+0

Esta es de hecho la mejor solución propuesta. – gnzlbg

3

respuesta más simple es utilizar vector<struct sb> donde sb es struct {boolean b};. Entonces puedes decir push_back({true}). Parece bien.