La motivation pour cette extension, qui est détectable par un programme conforme, et donc non conforme, est de faire de la vector<bool>
se comportent plus comme des vector<char>
à l'égard de références (const et autre).
Introduction
Depuis 1998, vector<bool>
a été considéré comme "pas tout à fait un conteneur." LWG 96, l'un des tout premiers LWG questions, a lancé le débat. Aujourd'hui, 17 ans plus tard, vector<bool>
reste en grande partie inchangée.
Le présent document passe en certains exemples spécifiques sur la façon dont le comportement de l' vector<bool>
diffère de tous les autres instanciation d' vector
, portant ainsi préjudice code générique. Toutefois, le même article discute longuement de la très belle performance de propriétés vector<bool>
peut avoir, si elle est correctement mise en œuvre.
Résumé: vector<bool>
n'est pas un mauvais conteneur. Il est tout à fait utile. Il a juste un mauvais nom.
Retour à l' const_reference
Comme présenté ci-dessus, et qui sont détaillés ici, ce qui est mauvais sur vector<bool>
, c'est qu'il se comporte différemment dans le code générique que les autres vector
instanciations. Voici un exemple concret:
#include <cassert>
#include <vector>
template <class T>
void
test(std::vector<T>& v)
{
using const_ref = typename std::vector<T>::const_reference;
const std::vector<T>& cv = v;
const_ref cr = cv[0];
assert(cr == cv[0]);
v[0] = 1;
assert(true == cv[0]);
assert(cr == cv[0]); // Fires!
}
int
main()
{
std::vector<char> vc(1);
test(vc);
std::vector<bool> vb(1);
test(vb);
}
La spécification de la norme dit que l'assertion marquée // Fires!
va déclencher, mais seulement lorsque l' test
est exécuté avec un vector<bool>
. Lors de l'exécution avec un vector<char>
(ou tout vector
en plus d' bool
lorsqu'une non-valeur par défaut T
est affectée), le test passe.
La libc++ mise en œuvre cherché à minimiser les effets négatifs de l'avoir vector<bool>
se comportent différemment dans le code générique. Une chose qu'il a fait pour y parvenir est de faire vector<T>::const_reference
un proxy de référence, tout comme le spécifiée vector<T>::reference
, sauf que vous ne pouvez pas assigner à travers elle. C'est, sur la libc++, vector<T>::const_reference
est essentiellement un pointeur vers la peu l'intérieur de l' vector
, au lieu d'une copie de ce bit.
Sur la libc++ ci-dessus test
passe pour les deux vector<char>
et vector<bool>
.
À quel coût?
L'inconvénient est que cette extension est détectable, comme indiqué dans la question. Cependant, très peu de programmes de soins sur le type exact de cet alias, et plus de programmes de soins sur le comportement.
Quelle est la motivation de cette non-conformité?
Pour donner de la libc++ client un meilleur comportement dans le code générique, et peut-être après un essai sur le terrain, proposer cette extension à une future norme C++ pour l'amélioration de l'ensemble de C++ de l'industrie.
Une telle proposition pourrait prendre la forme d'un nouveau conteneur (par exemple, bit_vector
) qui a le même API, comme aujourd'hui, vector<bool>
, mais avec quelques améliorations telles que l' const_reference
discutés ici. Suivie par la dépréciation (et de l'éventuelle suppression) de l' vector<bool>
de la spécialisation. bitset
pourrait également utiliser un peu de mise à niveau dans ce département, par exemple, ajouter const_reference
, et un ensemble d'itérateurs.
C'est, avec le recul bitset
est vector<bool>
(ce qui devrait être renommé bit_vector
-- ou quoi que ce soit), que array
est vector
. Et l'analogie doit être vrai si oui ou non nous parlons bool
le value_type
de vector
et array
.
Il existe plusieurs exemples de C++11 et C++14 caractéristiques qui ont commencé comme des extensions dans la libc++. C'est la façon dont les normes évoluent. Réelle démontré positive de l'expérience de terrain, exerce une forte influence. Les normes folk est un conservateur tas quand il s'agit de changer les spécifications existantes (comme ils devraient l'être). Deviner, même lorsque vous êtes sûr de deviner correctement, est une stratégie risquée pour l'évolution d'une norme internationalement reconnue.