Warum ist std::vector<bool> kein Container?
-
Ich habe vor laengerm mal den Artikel What You Should Know about vector<bool> gelesen.
Dort steht folgender Satz:
Defect Report (DR) 96 states that vector<bool> is not a container, as its reference and pointer types are not references and pointers, [...]
Ich verstehe diesen Satz nicht ganz. Ich glaube es liegt daran, dass ich nicht genau verstehe wann etwas als Container gilt und wann nicht. Kann mir das jemand kurz erklaeren?
-
icarus2 schrieb:
Ich habe vor laengerm mal den Artikel What You Should Know about vector<bool> gelesen.
Dort steht folgender Satz:
Defect Report (DR) 96 states that vector<bool> is not a container, as its reference and pointer types are not references and pointers, [...]
Ich verstehe diesen Satz nicht ganz. Ich glaube es liegt daran, dass ich nicht genau verstehe wann etwas als Container gilt und wann nicht. Kann mir das jemand kurz erklaeren?
Der Standard legt fest, was er unter einem Container versteht.
Unter anderem speichert jeder Container Objekte seines value_type und erlaubt den direkten Zugriff per Zeiger oder Referenz (23.2).
Für vector<bool, A> trifft das aber nicht zu. Da der Standard widerspruchsfrei sein soll, funktioniert das nur, wenn wir vector<bool, A> nicht als Container im Sinne des Standards betrachten.
-
Das Problem ist, dass
std::vector<bool>
als template-spezifikation nur einen Bit pro Objekt (Boolean) verbrauchen soll, um (verständlicherweise) Speicherplatz zu sparen - so dachten die Typen vom Standard sich das. Das ist ja schön und gut, nur sind jetzt Zeiger und Referenzen auf Bits nicht möglich (da, wie du wissen solltest, ein Byte die kleinste addressierbare Einheit in einem Computer ist (und das aus guten Gründen)).
-
Was mich jetzt allerdings verwirrt, ist die Bit-Referenz:
#include <iostream> #include <vector> #include <typeinfo> int main() { std::vector<bool> a(5, false); auto b = &a[3]; std::cout << typeid(*b).name() << '\n'; }
std::cout schrieb:
St14_Bit_reference
-
was verwirrt dich? Der Container gibt ein Proxy-Object zurück, das sich genau wie bool verhält (bis auf die Kleinigkeit, dass es wohl nicht nach bool& castbar ist)
-
otze schrieb:
was verwirrt dich? Der Container gibt ein Proxy-Object zurück, das sich genau wie bool verhält (bis auf die Kleinigkeit, dass es wohl nicht nach bool& castbar ist)
Hast Recht, aber ist std::_Bit_reference jetzt eig. standardisiert oder IB?
-
Achso, ich wusste nicht, dass der Standard festlegt, dass der direkte Zugriff per Zeiger oder Referenz moeglich sein muss. Damit ist klar, warum std::vector<bool> ein Container im Sinne des Standards ist.
Danke fuer die Erklaerungen.
-
Hacker schrieb:
Hast Recht, aber ist std::_Bit_reference jetzt eig. standardisiert oder IB?
da braucht man nichtmal in den Standard schauen: der Name beginnt mit _B was ein vom Standard geschützter Name ist, der nur vom Compilerbauer verwendet werden darf.
Das was du benutzen darfst ist std::vector<bool>::reference
-
otze schrieb:
Hacker schrieb:
Hast Recht, aber ist std::_Bit_reference jetzt eig. standardisiert oder IB?
da braucht man nichtmal in den Standard schauen: der Name beginnt mit _B was ein vom Standard geschützter Name ist, der nur vom Compilerbauer verwendet werden darf.
Das was du benutzen darfst ist std::vector<bool>::reference
Meinst du konkret das _B mit 'B' oder einfach nur den Unterstrich?
-
Hacker schrieb:
... template-spezifikation ...
Da das hier nicht das erste mal ist, dass ich von Dir in diesem Kontext diesen Ausdruck lese, möchte ich darauf hinweisen, dass Du wahrsheinlich eine Spezialisierung und keine Spezifikation meinst.
-
krümelkacker schrieb:
Hacker schrieb:
... template-spezifikation ...
Da das hier nicht das erste mal ist, dass ich von Dir in diesem Kontext diesen Ausdruck lese, möchte ich darauf hinweisen, dass Du wahrsheinlich eine Spezialisierung und keine Spezifikation meinst.
Jup.
Verwechsle die beiden leider oft.
-
Hacker schrieb:
Meinst du konkret das _B mit 'B' oder einfach nur den Unterstrich?
standard sagt: alles was mit __ oder _GROSZBUCHSTABE beginnt, ist ein geschützter Name. Ich vermute, damit ist die Verwendung sogar UB
-
Alle Bezeichner die:
1. mit einem Unterstrich gefolgt von einem Großbuchstaben beginnen
2. zwei Unterstriche in Folge beinhalten (egal ob am Anfang oder sonstwo) oder
3. sich im globalen Namensraum befinden und mit einem Unterstrich beginnensind für die Implementation reserviert (gemeint ist die Implementation des C++-Standards, also den Compiler und die Standardbibliothek). Ob es undefiniertes Verhalten erzeugt, sie zu benutzen, ist eine interessante Frage - da es dem Compiler freisteht, sie als Makros beliebigen Inhalts zu definieren, ist es streng genommen wohl so. In der Praxis steht aber zu erwarten, dass es im Konfliktfall Compilerfehler hagelt.