Selon https://en.cppreference.com/ , std::vector<bool>
a une spécialisation de modèle de classe, std::array<bool, N>
. Quelles sont les raisons pour lesquelles il n'est pas fourni?
4 Réponses :
C'est une question sur l'histoire de l'évolution du C ++. Avec le recul, une explication possible est:
std::vector<bool>
était une erreur. Le fait qu'un std::vector<bool>
soit très différent de std::vector<T>
est un inconvénient majeur. Le code générique qui fonctionne avec les vector
souvent besoin d'un cas particulier pour std::vector<bool>
. Et les utilisateurs doivent souvent appliquer des solutions de contournement étranges comme l'utilisation d'un std::vector<char>
à la place de std::vector<bool>
. Maintenant, nous ne pouvons pas revenir en arrière sans casser beaucoup de code existant. Avec ce que nous savons maintenant, peut-être que std::vector<bool>
ne serait jamais entré en C ++.
std::array
été ajouté uniquement en C ++ 11. Il n'y avait aucune raison de refaire la même erreur.
Lorsque std::vector
été introduit, une spécialisation pour bool
était considérée comme une bonne idée. Fondamentalement, à ce moment-là, l'ordinateur moyen avait 4 Mo de mémoire, donc économiser la mémoire de l'ordinateur était assez important. De nos jours, nous disons simplement "la mémoire est bon marché" (citation de l'oncle Bob).
Plus tard, il s'est avéré que cette spécialisation créait plus de problèmes qu'elle n'en valait la peine.
Le problème est que l'adresse à l'un des éléments d'un tel vecteur est un objet complexe (il doit stocker des informations sur quel bit contient quelle valeur) par rapport au bool a[]
.
Puisque la compatibilité doit être conservée, cette spécialisation ne peut pas être supprimée, mais sur la base de cette leçon, la même approche n'a pas été appliquée à std::array
.
Une autre raison est que std::array
est supposé être un wrapper C-array, donc il doit être aussi similaire que possible à bool a[N]
, et doit produire le même code machine lorsqu'il est utilisé.
Et la dernière chose, comme le souligne Cody Gray dans un commentaire sous question , std::bitset
est un tableau de bits de taille constante, donc une telle fonctionnalité est déjà disponible (et peut être utilisée si nécessaire).
Excellente réponse, +1. Cependant, veuillez ne pas utiliser de formatage de code pour le texte non codé: cela peut interférer avec les technologies de navigation alternatives, par exemple les lecteurs d'écran pour les aveugles, et ainsi rendre le site moins accessible.
La spécialisation std::vector<bool>
été introduite dès 1994, selon lib.vector.bool de WG21 / N0545 (1) [c'est moi qui souligne ]:
23.1.6
vector<bool>
classevector<bool>
[lib.vector.bool]Pour optimiser l'allocation d'espace , une spécialisation pour
bool
est fournie: [...]
avec une motivation pour optimiser l'allocation de l'espace, une ressource qui était rare à l'époque.
Rétrospectivement, cela s'est avéré être une très mauvaise idée, et la motivation initiale a été rendue discutable avec la croissance rapide de l'espace disponible dans le matériel informatique.
std::array
, d'autre part, a été introduit beaucoup plus tard, en C ++ 11, aux côtés par exemple de auto
déduction auto
type, un mécanisme qui a mis en évidence un autre problème avec la spécialisation std::vector<bool>
. Naturellement, les rédacteurs de spécifications de la bibliothèque n'ont pas répété la même erreur de std::vector<bool>
lors de la conception de std::array
.
Par exemple, l'extrait suivant
error: static_assert failed due to requirement 'std::is_same_v< std::__1::__bit_reference< std::__1::vector<bool, std::__1::allocator<bool>>, true>, bool>' ""
échoue avec le message d'erreur que bool_value
n'est pas de type bool
, mais de type cryptique (défini par l'implémentation)
#include <type_traits> #include <vector> int main() { std::vector<bool> v{false, false, true, true}; auto bool_value = v[1]; static_assert(std::is_same_v<decltype(bool_value), bool>, ""); // Error! }
(1) Document de travail pour l'avant-projet de norme internationale pour les systèmes d'information - Langage de programmation C ++.
La motivation initiale pour spécialiser std::vector
pour bool
était d'optimiser l'utilisation de la mémoire.
Cependant, c'était une mauvaise idée car cette spécialisation se comporte différemment de std::vector
habituel (voir l'exemple ci-dessous).
Cette erreur n'a pas été reproduite plus tard avec std::array
C ++ 11
#include <array> #include <vector> int main() { std::vector<int> i_v(4); int i_a = *&i_v[3]; // ok std::vector<bool> v(4); bool a = *&v[3]; // Compile-time error std::array<bool,4> w; bool b = *&w[3]; // ok }
Parce que cela est déjà fourni par
std::bitset
.