Pourquoi vector :: reference ne renvoie pas de référence à bool?

#include  struct A { void foo(){} }; template void callIfToggled( bool v1, bool &v2, T & t ) { if ( v1 != v2 ) { v2 = v1; t.foo(); } } int main() { std::vector v= { false, true, false }; const bool f = false; A a; callIfToggled( f, v[0], a ); callIfToggled( f, v[1], a ); callIfToggled( f, v[2], a ); } 

La compilation de l’exemple ci-dessus génère l’erreur suivante:

 dk2.cpp: In function 'int main()': dk2.cpp:29:28: error: no matching function for call to 'callIfToggled(const bool&, std::vector::reference, A&)' dk2.cpp:29:28: note: candidate is: dk2.cpp:13:6: note: template void callIfToggled(bool, bool&, T&) 

J’ai compilé en utilisant g ++ (version 4.6.1) comme ceci:

 g++ -O3 -std=c++0x -Wall -Wextra -pedantic dk2.cpp 

La question est pourquoi cela se produit? Le vector::reference n’est-il pas bool& ? Ou est-ce un bug du compilateur?
Ou est-ce que j’essaye quelque chose de stupide? 🙂

Vector est spécialisé pour bool .

C’est considéré comme une erreur du std. Utilisez plutôt le vector :

 template struct foo { using type = t; }; template<> struct foo { using type = char; }; template using fixed_vector = std::vector::type, p...>; 

Parfois, vous pouvez avoir besoin de références à un bool contenu dans le vecteur. Malheureusement, l’utilisation de vector ne peut vous donner que des références à des caractères. Si vous avez vraiment besoin de bool& , consultez la bibliothèque Boost Containers . Il a une version non spécialisée du vector .

Vos attentes sont normales, mais le problème est que std::vector a été une sorte d’expérience du comité C ++. C’est en fait une spécialisation de modèle qui stocke les valeurs bool étroitement empaquetées en mémoire: un bit par valeur.

Et comme vous ne pouvez pas avoir une référence à un peu, il y a votre problème.

std::vector est un conteneur non conforme. Pour optimiser l’espace, il emballe bool s et ne peut pas fournir de référence.

Utilisez plutôt boost::dynamic_bitset place.

std::vector< bool > emballe son contenu pour que chaque valeur booléenne soit stockée sur un bit, huit bits sur un octet. Ceci est efficace en termes de mémoire mais nécessite beaucoup de calculs, car le processeur doit effectuer des opérations arithmétiques pour accéder au bit demandé. Et cela ne fonctionne pas avec la référence bool ou la sémantique du pointeur, puisque les bits dans un octet n’ont pas d’adresse dans le modèle d’object C ++.

Vous pouvez toujours déclarer une variable de type std::vector::reference et l’utiliser comme si elle était bool& . Cela permet aux algorithmes génériques d’être compatibles.

 std::vector< bool > bitvec( 22 ); std::vector< bool >::reference third = bitvec[ 2 ]; third = true; // assign value to referenced bit 

En C ++ 11, vous pouvez contourner ce problème en utilisant auto et le spécificateur && qui sélectionne automatiquement une référence lvalue liée à l’élément vectoriel ou une référence rvalue liée à un temporaire.

 std::vector< bool > bitvec( 22 ); auto &&third = bitvec[ 2 ]; // obtain a std::vector< bool >::reference third = true; // assign value to referenced bit 

Juste mes 2 centimes:

std::vector::reference est un typedef pour struct _Bit_reference qui est défini comme

 typedef unsigned long _Bit_type; struct _Bit_reference { _Bit_type * _M_p; _Bit_type _M_mask; // constructors, operators, etc... operator bool() const { return !!(*_M_p & _M_mask); } }; 

Changer la fonction comme ça, ça marche (enfin, comstack au moins, pas testé):

 template< typename T > void callIfToggled( bool v1, std::vector::reference v2, T & t ) { bool b = v2; if ( v1 != b ) { v2 = v1; t.foo(); } } 

EDIT: J’ai changé la condition de (v1! = V2), ce qui n’était pas une bonne idée, à (v1! = B).

Créez une structure avec un bool et créez le vector<> utilisant ce type de structure.

Essayer:

vectorsb est struct {boolean b];

alors vous pouvez dire

push_back({true})

faire

typedef struct sbool {bool b;} boolstruct; puis vector bs;