2009-03-22 11 views
77

As (hoffentlich) wir alle wissen, vector<bool> total kaputt ist und nicht als c-Array behandelt werden. Was ist der beste Weg, um diese Funktionalität zu bekommen? Bisher haben die Ideen, die ich gedacht sind:Alternative zum Vektor <bool>

  • stattdessen ein vector<char> verwenden oder
  • Verwenden Sie eine Wrapper-Klasse und haben vector<bool_wrapper>

Wie euch dieses Problem umgehen? Ich brauche die c_array() Funktionalität.

Als Seite Frage, ob ich() -Methode nicht das c_array benötigen, was ist der beste Weg, um dieses Problem zu nähern, wenn ich mit wahlfreiem Zugriff benötigen? Soll ich eine Deque oder etwas anderes benutzen?

Edit:

  • ich dynamische Dimensionierung tun müssen.
  • Für diejenigen, die nicht wissen, ist vector<bool> spezialisiert, so dass jeder Bool 1 Bit nimmt. Daher können Sie es nicht in ein c-artiges Array konvertieren.
  • Ich denke, "Wrapper" ist ein bisschen falsch. Ich war so etwas wie dieses Denken:

Natürlich dann muss ich wegen möglicher Ausrichtungsprobleme in eine my_bool lesen :(

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

Gibt es einen Grund, nicht ... ein C-artiges Array zu verwenden? – kquinn

+0

rlbond, brauchen Sie dynamische Größe? –

+14

Ok ich beiße -. Warum Vektor "" total kaputt“ist –

Antwort

35

Verwenden std::deque, wenn Sie nicht das Array benötigen, ja .

Ansonsten ein alternatives vector verwenden, die nicht in Boost Container auf bool, wie die sich spezialisiert hat.

+1

Warum nicht verwenden 'boost :: Container :: VECTOR' die für' bool' funktioniert wie erwartet – gnzlbg

+1

@gnzlbg - gut Anruf, ich habe die Antwort aktualisiert (ich postete es über zwei Jahre, bevor Container zu Boost hinzugefügt wurde!) –

14

Abhängig von Ihren Bedürfnissen. ich w ould gehen entweder std::vector<unsigned char>. Das Schreiben eines Wrappers kann in Ordnung sein, wenn Sie nur eine Teilmenge der Funktionalität verwenden, sonst wird es ein Albtraum.

20

Das ist ein interessantes Problem.

Wenn Sie benötigen, was ein std gewesen wäre :: vector, wenn es nicht spezialisiert ist, dann vielleicht so etwas wie das wäre mit Ihrem Fall funktionieren:

#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; 
} 

Ich versuchte dies mit VC9 und es scheint funktioniert gut. Die Idee der Bool-Klasse besteht darin, den Bool-Typ zu simulieren, indem dasselbe Verhalten und dieselbe Größe (aber nicht der gleiche Typ) bereitgestellt wird. Fast alle Arbeiten werden vom Bool-Operator und den Standard-Kopierkonstruktoren hier erledigt. Ich fügte eine Sortierung hinzu, um sicher zu sein, dass sie so reagiert, wie es bei der Verwendung von Algorithmen angenommen wurde.

Nicht sicher wäre es auf alle Fälle gerecht wird. Wenn es für Ihre Bedürfnisse richtig ist, wäre es weniger Arbeit als eine Vektor-ähnliche Klasse Umschreiben ...

+0

nicht vollständige Lösung Sie können nicht schreiben etwas wie: bool * b = &v[0]; – bayda

+0

Das stimmt, Sie können es nur neu interpretieren. – Klaim

+2

als Lösung könnten wir hinzufügen bool * operator &() {return & m_value; } und Konvertierung in Const Bool *, Bool & Const Bool &. Aber trotzdem - Hauptidee ist richtig. – bayda

4

dieses Problem wurde bereits auf comp.lang.c diskutiert ++.moderierte (http://groups.google.ru/group/comp.lang.c++.moderated/browse_thread/thread/b8d6dd59dfb295c0/e23e0f606d64550a)
vorgeschlagenen Lösungen:

  • Ihr eigenes Allocator (basierend auf std :: Allocator) und eigene Vektor Spezialisierung;
  • Verwenden Sie Std :: Deque (so früh wurde in einem der Bücher S. Mayers empfohlen) - aber das ist nicht für Ihre Anforderungen;
  • machen POD Bool Wrapper;
  • Verwenden Sie etwas (char/int/etc) mit der gleichen Größe wie Bool statt Bool;

auch früh sah ich Vorschlag für Standard commitette - einführen Makro (so etwas wie STD_VECTOR_BOOL_SPECIAL) für dissallow diese Spezialisierung - aber afaik diesem Vorschlag wurde nicht in stl Implementierungen umgesetzt und wurde nicht approoved.

es scheint, dass Ihr Problem keine Möglichkeiten hat dies gut zu tun .. vielleicht in C++ 0x

5

Betrachten wir ein Vektor < int verwenden>. Sobald Sie die Kompilierung und Typprüfung hinter sich haben, sind bool und int beides nur Maschinenwörter (edit: anscheinend ist das nicht immer wahr; trifft aber auf vielen PC-Architekturen zu). In den Fällen, in denen Sie ohne Warnung konvertieren möchten, verwenden Sie "bool foo = !! bar", die Null in false und nicht von null in true konvertiert.

Ein Vektor < Zeichen> oder ähnliches benötigt weniger Platz, obwohl er unter bestimmten Umständen auch einen (sehr kleinen) Geschwindigkeitstreffer haben kann, weil Zeichen kleiner als die Maschinenwortgröße sind. Dies ist, glaube ich, der Hauptgrund dafür, dass Bools mit Ints anstelle von Chars implementiert werden.

Wenn Sie wirklich saubere Semantik wollen, mag ich auch den Vorschlag, Ihre eigene boolesche Klasse - sieht aus wie ein Bool, wirkt wie ein Bool, aber täuscht die Template-Spezialisierung.

Willkommen auch im Club der Leute, die den Vektor < bool> Spezialisierung aus dem C++ - Standard (mit bit_vector ersetzt werden soll). Es ist, wo alle coolen Kinder abhängen :).

+5

Bool und Int sind nicht beide Maschinenwörter. Auf dem System entwickle ich für, sizeof (bool) = 1 und sizeof (int) = 4. Die Ausrichtungsanforderungen und die generierten Lade-/Speicheranweisungen unterscheiden sich entsprechend. – leander

10

Wie geht ihr mit diesem Problem um? Ich brauche die c_array() Funktionalität.

boost::container::vector<bool>:

Vektor < Bool> Spezialisierung ist ziemlich problematisch, und es wurden mehrere erfolglose Versuche gewesen, es von der Norm zu verbitten oder zu entfernen. Boost.Container implementiert es nicht, da es eine überlegene Boost.DynamicBitset Lösung gibt.

...

So boost :: Container :: vector :: iterator kehrt echte Bool Referenzen und arbeitet als voll kompatibel Behälter. Wenn Sie eine speicheroptimierte Version von boost :: container :: vector < bool> Funktionen benötigen, verwenden Sie bitte Boost.DynamicBitset.

+0

Dies ist in der Tat die beste vorgeschlagene Lösung. – gnzlbg

3

einfachste Antwort ist vector<struct sb> zu verwenden, wo sbstruct {boolean b}; ist. Dann können Sie sagen push_back({true}). Es scheint gut.

Verwandte Themen