Les types que vous mettez dans un conteneur standard doivent être copiables et assignables. La raison pour laquelle auto_ptr
cause tant de problèmes est précisément parce qu'il ne suit pas la sémantique normale de copie et d'affectation. Naturellement, tout ce qui est const
ne sera pas cessible. Donc, vous ne pouvez pas coller const
n'importe quoi dans un conteneur standard. Et si l'élément n'est pas const
alors vous sont va être capable de le changer.
La solution la plus proche qui me semble possible serait d'utiliser une sorte d'indirection. Ainsi, vous pourriez avoir un pointeur vers const ou vous pourriez avoir un objet qui contient la valeur que vous voulez mais la valeur ne peut pas être changée dans l'objet (comme vous auriez avec Integer
en Java).
Le fait que l'élément à un indice particulier soit immuable va à l'encontre du fonctionnement des conteneurs standard. Vous pourriez être en mesure de construire vos propres conteneurs qui fonctionnent de cette façon, mais les conteneurs standard ne le font pas. Et aucun de ceux qui sont basés sur des tableaux ne fonctionnera de toute façon, à moins que vous ne parveniez à faire entrer leur initialisation dans la section {a, b, c}
syntaxe d'initialisation, car une fois qu'un tableau de const
a été créé, vous ne pouvez pas le modifier. Ainsi, un vector
n'est pas susceptible de fonctionner avec des éléments constants, quoi que vous fassiez.
Avoir const
dans un conteneur sans une certaine forme d'indirection ne fonctionne pas très bien. Vous demandez essentiellement à ce que l'ensemble du conteneur const
- ce que vous pouvez faire si vous le copiez à partir d'un conteneur déjà initialisé, mais vous ne pouvez pas vraiment avoir un conteneur - certainement pas un conteneur standard - qui contient des constantes sans une sorte d'indirection.
EDITAR : Si ce que vous cherchez à faire est de laisser la plupart du temps un conteneur inchangé mais de pouvoir le modifier à certains endroits du code, alors utiliser une réf const dans la plupart des endroits et donner ensuite au code qui doit pouvoir modifier le conteneur un accès direct ou une réf non const permettrait de le faire.
Donc, utilisez const vector<int>&
dans la plupart des endroits, et ensuite soit vector<int>&
où vous devez modifier le conteneur, ou donner à cette partie du code un accès direct au conteneur. De cette façon, il est pratiquement invariable, mais vous pouvez le modifier quand vous le souhaitez.
D'un autre côté, si vous voulez être en mesure de toujours modifier ce qui se trouve dans le conteneur, mais pas des éléments spécifiques, je vous suggère de mettre une classe enveloppante autour du conteneur. Dans le cas de vector
Il faut donc l'envelopper et faire en sorte que l'opérateur d'indice renvoie une réf. const au lieu d'une réf. non const - soit cela, soit une copie. Ainsi, en supposant que vous ayez créé une version modélisée, votre opérateur d'indice ressemblerait à quelque chose comme ceci :
const T& operator[](size_t i) const
{
return _container[i];
}
De cette façon, vous pouvez mettre à jour le conteneur lui-même, mais vous ne pouvez pas modifier ses éléments individuels. Et tant que vous déclarez toutes les fonctions inline, l'utilisation du wrapper ne devrait pas avoir de répercussions importantes sur les performances (voire aucune).