j'ai mis à jour mon gcc (g++ : 3.3.6->3.4.4) et un code tout bête qui
compilait ne compile plus, sans que j'arrive à comprendre pourquoi.
C'est bête car il s'agit juste de parcourir une liste "constante"
contenant des chaînes "constantes", transmise par référence, avec un
'const_iterator' : (j'ai laissé le code tel quel pour ne pas rajouter
d'erreur, il s'agit d'une fonction utilitaire pour un système de log à
même de générer deux cibles, texte brut et document HTML)
(j'ai rajouté ----> pour indiquer la ligne qui lui pose problème)
if ( TextDisplayable::GetOutputFormat() == TextDisplayable::html )
{
res = "<ul>" ;
----> for ( list<const string>::const_iterator it =
stringList.begin(); it != stringList.end();
it++ )
res += "<li>" + ( *it ) + "</li>" ;
res += "</ul>" ;
}
else
{
// Raw text :
res = '\n' ;
for ( list<const string>::const_iterator it = stringList.begin(); it
!= stringList.end();
it++ )
res += "\t+ " + ( *it ) + '\n' ;
}
return res ;
}
"""
L'erreur (abominable bien sûr avec la STL) qu'il me sort est la suivante :
"""
[..]/include/c++/3.4.4/ext/new_allocator.h: In instantiation of
`__gnu_cxx::new_allocator<const std::string>':
[...] endroits d'instanciation puis :
[..]/include/c++/3.4.4/ext/new_allocator.h:75: error: `const _Tp*
__gnu_cxx::new_allocator<_Tp>::address(const _Tp&) const [with _Tp =
const std::string]' and `_Tp*
-_gnu_cxx::new_allocator<_Tp>::address(_Tp&) const [with _Tp = const
std::string]' cannot be overloaded
"""
Bien sûr j'utilise des std::string "telles quelles", c'est-à-dire sans
les avoir sous-classées et sans avoir redéfini new ou quoi que ce soit
de suspect à mes yeux (à part un opérateur permettant de concaténer
std::string et (const) char * mais cela ne devrait pas avoir de lien)
Est-ce que quelqu'un comprendrait pourquoi il refuse désormais de
compiler cela, et comment je pourrais quand même lui spécifier
d'utiliser néanmoins une liste de chaînes, transmise par référence, en
déclarant modifier ni la liste ni les chaînes ?
----> for ( list<const string>::const_iterator it >
Les éléments d'une std::list doivent être copiables, ce qui n'est pas le cas d'un const string.
Tu veux dire affectable, je crois. On peut copier (constructeur de copie) un const, mais on ne peut pas en affecter (operator=) un.
Tout à fait.
-- Loïc
Olivier Boudeville
Merci à tous pour votre aide, je ne pensais pas que changer de version de gcc ferait émerger des erreurs de ce type !
En toute logique, n'aurait -il pas dû refuser un type non conforme (list<const X>) plutôt que de râler seulement quand on l'utilise via un itérateur ? Et donc est-ce que la STL ne propose pas de conteneurs de 'const' sur lesquels on puisse itérer ? C'est quand même une fonctionnalité élémentaire et utile ? Plus le temps passe plus je pense que finalement ces conteneurs sont pratiques avant tout pour stocker des pointeurs sur objets plutôt que des objets.
En tout cas merci beaucoup pour l'aide et désolé pour les posts multiples, mon client de news (thunderbird) m'affirmait à tort ne rien avoir envoyé (et il a fallu que j'accède à http://groups-beta.google.com/group/fr.comp.lang.c++ pour lire les réponses !)
Olivier.
Loïc Joly wrote:
Loïc Joly wrote:
----> for ( list<const string>::const_iterator it >>
Les éléments d'une std::list doivent être copiables, ce qui n'est pas le cas d'un const string.
Tu veux dire affectable, je crois. On peut copier (constructeur de copie) un const, mais on ne peut pas en affecter (operator=) un.
Tout à fait.
Merci à tous pour votre aide, je ne pensais pas que changer de version
de gcc ferait émerger des erreurs de ce type !
En toute logique, n'aurait -il pas dû refuser un type non conforme
(list<const X>) plutôt que de râler seulement quand on l'utilise via un
itérateur ? Et donc est-ce que la STL ne propose pas de conteneurs de
'const' sur lesquels on puisse itérer ? C'est quand même une
fonctionnalité élémentaire et utile ? Plus le temps passe plus je pense
que finalement ces conteneurs sont pratiques avant tout pour stocker des
pointeurs sur objets plutôt que des objets.
En tout cas merci beaucoup pour l'aide et désolé pour les posts
multiples, mon client de news (thunderbird) m'affirmait à tort ne rien
avoir envoyé (et il a fallu que j'accède à
http://groups-beta.google.com/group/fr.comp.lang.c++ pour lire les
réponses !)
Olivier.
Loïc Joly wrote:
Loïc Joly wrote:
----> for ( list<const string>::const_iterator it >>
Les éléments d'une std::list doivent être copiables, ce qui
n'est pas le cas d'un const string.
Tu veux dire affectable, je crois. On peut copier (constructeur
de copie) un const, mais on ne peut pas en affecter (operator=)
un.
Merci à tous pour votre aide, je ne pensais pas que changer de version de gcc ferait émerger des erreurs de ce type !
En toute logique, n'aurait -il pas dû refuser un type non conforme (list<const X>) plutôt que de râler seulement quand on l'utilise via un itérateur ? Et donc est-ce que la STL ne propose pas de conteneurs de 'const' sur lesquels on puisse itérer ? C'est quand même une fonctionnalité élémentaire et utile ? Plus le temps passe plus je pense que finalement ces conteneurs sont pratiques avant tout pour stocker des pointeurs sur objets plutôt que des objets.
En tout cas merci beaucoup pour l'aide et désolé pour les posts multiples, mon client de news (thunderbird) m'affirmait à tort ne rien avoir envoyé (et il a fallu que j'accède à http://groups-beta.google.com/group/fr.comp.lang.c++ pour lire les réponses !)
Olivier.
Loïc Joly wrote:
Loïc Joly wrote:
----> for ( list<const string>::const_iterator it >>
Les éléments d'une std::list doivent être copiables, ce qui n'est pas le cas d'un const string.
Tu veux dire affectable, je crois. On peut copier (constructeur de copie) un const, mais on ne peut pas en affecter (operator=) un.
Tout à fait.
Michel Michaud
Dans le message dctt3h$hf0$,
En toute logique, n'aurait -il pas dû refuser un type non conforme (list<const X>) plutôt que de râler seulement quand on l'utilise via un itérateur ?
Essaie d'écrire ce genre de conteneur, tu verras pourquoi...
Et donc est-ce que la STL ne propose pas de conteneurs de 'const' sur lesquels on puisse itérer ? C'est quand même une fonctionnalité élémentaire et utile ?
Essaie d'écrire ce genre de conteneur, tu verras pourquoi...
:-)
Par ailleurs, si tu veux une classe de données non modifiables, tu peux en faire une...
Plus le temps passe plus je pense que finalement ces conteneurs sont pratiques avant tout pour stocker des pointeurs sur objets plutôt que des objets.
Mais non. Certains diront même « au contraire ».
Le fait est que les classes de la bibliothèque ne sont que ça : des classes. Il n'y a pas de support particulier du compilateur pour reconnaître les caractéristiques de ce qui devrait être refusé (ou accepté). La chose à faire est normalement de lire la documentation. Tous les critères sont clairement indiqués dans la norme, entre autres.
Il y a actuellement des trucs assez sophistiqués qui permettent de faire certaines vérifications (mais pas toutes), mais le code ancien ne peut pas en tirer profit, car ces trucs n'étaient pas bien connus. Il y a aussi des suggestions pour que la prochaine version de C++ contienne des possibilités pour aider ce genre de vérifications.
-- Michel Michaud http://www.gdzid.com FAQ de fr.comp.lang.c++ : http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ/
Dans le message dctt3h$hf0$1@aphrodite.grec.isp.9tel.net,
En toute logique, n'aurait -il pas dû refuser un type non conforme
(list<const X>) plutôt que de râler seulement quand on l'utilise
via un itérateur ?
Essaie d'écrire ce genre de conteneur, tu verras pourquoi...
Et donc est-ce que la STL ne propose pas de
conteneurs de 'const' sur lesquels on puisse itérer ? C'est quand
même une fonctionnalité élémentaire et utile ?
Essaie d'écrire ce genre de conteneur, tu verras pourquoi...
:-)
Par ailleurs, si tu veux une classe de données non modifiables,
tu peux en faire une...
Plus le temps passe
plus je pense que finalement ces conteneurs sont pratiques avant
tout pour stocker des pointeurs sur objets plutôt que des objets.
Mais non. Certains diront même « au contraire ».
Le fait est que les classes de la bibliothèque ne sont que ça :
des classes. Il n'y a pas de support particulier du compilateur
pour reconnaître les caractéristiques de ce qui devrait être
refusé (ou accepté). La chose à faire est normalement de lire
la documentation. Tous les critères sont clairement indiqués
dans la norme, entre autres.
Il y a actuellement des trucs assez sophistiqués qui permettent
de faire certaines vérifications (mais pas toutes), mais le code
ancien ne peut pas en tirer profit, car ces trucs n'étaient pas
bien connus. Il y a aussi des suggestions pour que la prochaine
version de C++ contienne des possibilités pour aider ce genre de
vérifications.
--
Michel Michaud mm@gdzid.com
http://www.gdzid.com
FAQ de fr.comp.lang.c++ :
http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ/
En toute logique, n'aurait -il pas dû refuser un type non conforme (list<const X>) plutôt que de râler seulement quand on l'utilise via un itérateur ?
Essaie d'écrire ce genre de conteneur, tu verras pourquoi...
Et donc est-ce que la STL ne propose pas de conteneurs de 'const' sur lesquels on puisse itérer ? C'est quand même une fonctionnalité élémentaire et utile ?
Essaie d'écrire ce genre de conteneur, tu verras pourquoi...
:-)
Par ailleurs, si tu veux une classe de données non modifiables, tu peux en faire une...
Plus le temps passe plus je pense que finalement ces conteneurs sont pratiques avant tout pour stocker des pointeurs sur objets plutôt que des objets.
Mais non. Certains diront même « au contraire ».
Le fait est que les classes de la bibliothèque ne sont que ça : des classes. Il n'y a pas de support particulier du compilateur pour reconnaître les caractéristiques de ce qui devrait être refusé (ou accepté). La chose à faire est normalement de lire la documentation. Tous les critères sont clairement indiqués dans la norme, entre autres.
Il y a actuellement des trucs assez sophistiqués qui permettent de faire certaines vérifications (mais pas toutes), mais le code ancien ne peut pas en tirer profit, car ces trucs n'étaient pas bien connus. Il y a aussi des suggestions pour que la prochaine version de C++ contienne des possibilités pour aider ce genre de vérifications.
-- Michel Michaud http://www.gdzid.com FAQ de fr.comp.lang.c++ : http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ/
kanze
Olivier Boudeville wrote:
Merci à tous pour votre aide, je ne pensais pas que changer de version de gcc ferait émerger des erreurs de ce type !
En toute logique, n'aurait -il pas dû refuser un type non conforme (list<const X>) plutôt que de râler seulement quand on l'utilise via un itérateur ?
En toute logique, ça serait bien. Dans la pratique, le comité de normalisation a dit que c'est un comportement indéfini, et qu'il n'exige pas une erreur du compilateur, pour une raison. Le but, c'est que des classes et les fonctions de la bibliothèque peuvent s'implémenter, pour la plupart, en C++ même. Du coup, pour le compilateur, std::list, c'est une classe templatée comme une autre. Il existe une proposition d'ajouter des « conceptes », qui je crois résoudre ce problème, mais ce n'est qu'une proposition pour l'instant. Et s'il existe des techniques de la méta-programmation pour en faire une partie, au moins, ce sont des techniques assez récentes, et donc, pas présentes dans des implémentations courantes de la bibliothèque standard.
Et donc est-ce que la STL ne propose pas de conteneurs de 'const' sur lesquels on puisse itérer ?
Il y a une restriction au niveau de langage, qu'il n'y a qu'un seul « const » pour un objet donné. On peut lui en donner la signification qu'on veut (à peu près), mais on ne peut pas en créer deux, avec deux significations différentes.
Or, quand on considère une collection, il y a bien deux significations possibles : un const qui dit qu'on ne peut pas ajouter ou rétirer des objets (const « shallow » ?), et un const qui dit qu'on ne peut pas modifier des objets dans la collection (const profond ?). Quand tu conçois une collection, il faut bien que tu décides ce que doit signifier const : le premier, le deuxième, ou les deux. La STL a choisi les deux (ce qui me semble le compromis le plus raisonable).
En jouant sur les types, on pourrait créer des : vector_nonconst_aux_elements_const, vector_const_aux_elements_nonconst, etc. Mais c'est une sacrée complication -- pense aux questions des conversions implicites. Et note bien que les conversions de références ne marcheraient pas -- si tu as un vector_nonconst_aux_elements_nonconst, tu ne peux pas le passer à une fonction qui veut une référence à un vector_const_aux_elements_nonconst. Alors, j'ai de fortes doutes que la complexité supplémentaire en vaut la peine.
C'est quand même une fonctionnalité élémentaire et utile ? Plus le temps passe plus je pense que finalement ces conteneurs sont pratiques avant tout pour stocker des pointeurs sur objets plutôt que des objets.
Tout dépend. Au niveau applicatif, j'ai en fait beaucoup d'objets qui ne supportent pas l'affectation. Alors, les vecteurs de pointeurs s'imposent. D'autre côté, j'ai aussi des objets à sémantique de valeur, qui se comportent à beaucoup d'égards comme des int ou des double. Dans ces cas-là, un vecteur d'objets s'impose.
-- James Kanze GABI Software Conseils en informatique orientée objet/ Beratung in objektorientierter Datenverarbeitung 9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Olivier Boudeville wrote:
Merci à tous pour votre aide, je ne pensais pas que changer de
version de gcc ferait émerger des erreurs de ce type !
En toute logique, n'aurait -il pas dû refuser un type non
conforme (list<const X>) plutôt que de râler seulement quand
on l'utilise via un itérateur ?
En toute logique, ça serait bien. Dans la pratique, le comité de
normalisation a dit que c'est un comportement indéfini, et qu'il
n'exige pas une erreur du compilateur, pour une raison. Le but,
c'est que des classes et les fonctions de la bibliothèque
peuvent s'implémenter, pour la plupart, en C++ même. Du coup,
pour le compilateur, std::list, c'est une classe templatée comme
une autre. Il existe une proposition d'ajouter des
« conceptes », qui je crois résoudre ce problème, mais ce n'est
qu'une proposition pour l'instant. Et s'il existe des techniques
de la méta-programmation pour en faire une partie, au moins, ce
sont des techniques assez récentes, et donc, pas présentes dans
des implémentations courantes de la bibliothèque standard.
Et donc est-ce que la STL ne propose pas de conteneurs de
'const' sur lesquels on puisse itérer ?
Il y a une restriction au niveau de langage, qu'il n'y a qu'un
seul « const » pour un objet donné. On peut lui en donner la
signification qu'on veut (à peu près), mais on ne peut pas en
créer deux, avec deux significations différentes.
Or, quand on considère une collection, il y a bien deux
significations possibles : un const qui dit qu'on ne peut pas
ajouter ou rétirer des objets (const « shallow » ?), et un const
qui dit qu'on ne peut pas modifier des objets dans la collection
(const profond ?). Quand tu conçois une collection, il faut bien
que tu décides ce que doit signifier const : le premier, le
deuxième, ou les deux. La STL a choisi les deux (ce qui me
semble le compromis le plus raisonable).
En jouant sur les types, on pourrait créer des :
vector_nonconst_aux_elements_const,
vector_const_aux_elements_nonconst, etc. Mais c'est une sacrée
complication -- pense aux questions des conversions implicites.
Et note bien que les conversions de références ne marcheraient
pas -- si tu as un vector_nonconst_aux_elements_nonconst, tu ne
peux pas le passer à une fonction qui veut une référence à un
vector_const_aux_elements_nonconst. Alors, j'ai de fortes doutes
que la complexité supplémentaire en vaut la peine.
C'est quand même une fonctionnalité élémentaire et utile ?
Plus le temps passe plus je pense que finalement ces
conteneurs sont pratiques avant tout pour stocker des
pointeurs sur objets plutôt que des objets.
Tout dépend. Au niveau applicatif, j'ai en fait beaucoup
d'objets qui ne supportent pas l'affectation. Alors, les
vecteurs de pointeurs s'imposent. D'autre côté, j'ai aussi des
objets à sémantique de valeur, qui se comportent à beaucoup
d'égards comme des int ou des double. Dans ces cas-là, un
vecteur d'objets s'impose.
--
James Kanze GABI Software
Conseils en informatique orientée objet/
Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
Merci à tous pour votre aide, je ne pensais pas que changer de version de gcc ferait émerger des erreurs de ce type !
En toute logique, n'aurait -il pas dû refuser un type non conforme (list<const X>) plutôt que de râler seulement quand on l'utilise via un itérateur ?
En toute logique, ça serait bien. Dans la pratique, le comité de normalisation a dit que c'est un comportement indéfini, et qu'il n'exige pas une erreur du compilateur, pour une raison. Le but, c'est que des classes et les fonctions de la bibliothèque peuvent s'implémenter, pour la plupart, en C++ même. Du coup, pour le compilateur, std::list, c'est une classe templatée comme une autre. Il existe une proposition d'ajouter des « conceptes », qui je crois résoudre ce problème, mais ce n'est qu'une proposition pour l'instant. Et s'il existe des techniques de la méta-programmation pour en faire une partie, au moins, ce sont des techniques assez récentes, et donc, pas présentes dans des implémentations courantes de la bibliothèque standard.
Et donc est-ce que la STL ne propose pas de conteneurs de 'const' sur lesquels on puisse itérer ?
Il y a une restriction au niveau de langage, qu'il n'y a qu'un seul « const » pour un objet donné. On peut lui en donner la signification qu'on veut (à peu près), mais on ne peut pas en créer deux, avec deux significations différentes.
Or, quand on considère une collection, il y a bien deux significations possibles : un const qui dit qu'on ne peut pas ajouter ou rétirer des objets (const « shallow » ?), et un const qui dit qu'on ne peut pas modifier des objets dans la collection (const profond ?). Quand tu conçois une collection, il faut bien que tu décides ce que doit signifier const : le premier, le deuxième, ou les deux. La STL a choisi les deux (ce qui me semble le compromis le plus raisonable).
En jouant sur les types, on pourrait créer des : vector_nonconst_aux_elements_const, vector_const_aux_elements_nonconst, etc. Mais c'est une sacrée complication -- pense aux questions des conversions implicites. Et note bien que les conversions de références ne marcheraient pas -- si tu as un vector_nonconst_aux_elements_nonconst, tu ne peux pas le passer à une fonction qui veut une référence à un vector_const_aux_elements_nonconst. Alors, j'ai de fortes doutes que la complexité supplémentaire en vaut la peine.
C'est quand même une fonctionnalité élémentaire et utile ? Plus le temps passe plus je pense que finalement ces conteneurs sont pratiques avant tout pour stocker des pointeurs sur objets plutôt que des objets.
Tout dépend. Au niveau applicatif, j'ai en fait beaucoup d'objets qui ne supportent pas l'affectation. Alors, les vecteurs de pointeurs s'imposent. D'autre côté, j'ai aussi des objets à sémantique de valeur, qui se comportent à beaucoup d'égards comme des int ou des double. Dans ces cas-là, un vecteur d'objets s'impose.
-- James Kanze GABI Software Conseils en informatique orientée objet/ Beratung in objektorientierter Datenverarbeitung 9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34