26
votes

Pas de spécialisation de modèle de classe pour le tableau de booléens?

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?


1 commentaires

Parce que cela est déjà fourni par std::bitset .


4 Réponses :


13
votes

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.


0 commentaires

22
votes

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).


1 commentaires

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.



7
votes

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> classe vector<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 ++.


0 commentaires

9
votes

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
}


0 commentaires