[VC2005, STL] "could not deduce template argument"
8 réponses
Clement
Bonjour,
Voilà, j'ai un petit problème avec VC2005 que je ne rencontre pas avec
VC2003.net (je sais qu'ici, on ne parle pas des compilateurs, mais je
voudrais juste savoir si mon code est à la norme ou pas).
Voici le morceau de code en cause :
=============================================
#include <set>
class CSimplex;
typedef std::set<CSimplex>::iterator simplexIterator;
Dans une des fonctions membres de la classe CSimplex, j'appelle
m_children.insert(s) où s est un simplexIterator.
J'obtiens alors les erreurs de compilation suivantes :
1>------ Build started: Project: kd-tree v2, Configuration: Debug compress
Win32 ------
1>Compiling...
1>CSimplex.cpp
1>c:\program files\microsoft visual studio 8\vc\include\functional(143) :
error C2784: 'bool std::operator <(const std::vector<_Ty,_Alloc> &,const
std::vector<_Ty,_Alloc> &)' : could not deduce template argument for 'const
std::vector<_Ty,_Alloc> &' from 'const simplexIterator'
1> c:\program files\microsoft visual studio 8\vc\include\vector(1276) : see
declaration of 'std::operator <'
1> c:\program files\microsoft visual studio 8\vc\include\functional(142) :
while compiling class template member function 'bool
std::less<_Ty>::operator ()(const _Ty &,const _Ty &) const'
1> with
1> [
1> _Ty=simplexIterator
1> ]
1> c:\program files\microsoft visual studio 8\vc\include\set(60) : see
reference to class template instantiation 'std::less<_Ty>' being compiled
1> with
1> [
1> _Ty=simplexIterator
1> ]
1> c:\program files\microsoft visual studio 8\vc\include\xtree(26) : see
reference to class template instantiation
'std::_Tset_traits<_Kty,_Pr,_Alloc,_Mfl>' being compiled
1> with
1> [
1> _Kty=simplexIterator,
1> _Pr=std::less<simplexIterator>,
1> _Alloc=std::allocator<simplexIterator>,
1> _Mfl=true
1> ]
1> c:\program files\microsoft visual studio 8\vc\include\xtree(68) : see
reference to class template instantiation 'std::_Tree_nod<_Traits>' being
compiled
1> with
1> [
1>
_Traits=std::_Tset_traits<simplexIterator,std::less<simplexIterator>,std::allocator<simplexIterator>,true>
1> ]
1> c:\program files\microsoft visual studio 8\vc\include\xtree(94) : see
reference to class template instantiation 'std::_Tree_ptr<_Traits>' being
compiled
1> with
1> [
1>
_Traits=std::_Tset_traits<simplexIterator,std::less<simplexIterator>,std::allocator<simplexIterator>,true>
1> ]
1> c:\program files\microsoft visual studio 8\vc\include\xtree(112) : see
reference to class template instantiation 'std::_Tree_val<_Traits>' being
compiled
1> with
1> [
1>
_Traits=std::_Tset_traits<simplexIterator,std::less<simplexIterator>,std::allocator<simplexIterator>,true>
1> ]
1> c:\program files\microsoft visual studio 8\vc\include\set(178) : see
reference to class template instantiation 'std::_Tree<_Traits>' being
compiled
1> with
1> [
1>
_Traits=std::_Tset_traits<simplexIterator,std::less<simplexIterator>,std::allocator<simplexIterator>,true>
1> ]
1> d:\these\travail\vsprojects\kd-tree v2\core\csimplex.h(69) : see
reference to class template instantiation 'std::multiset<_Kty>' being
compiled
1> with
1> [
1> _Kty=simplexIterator
1> ]
1>c:\program files\microsoft visual studio 8\vc\include\functional(143) :
error C2784: 'bool std::operator <(const std::vector<_Ty,_Alloc> &,const
std::vector<_Ty,_Alloc> &)' : could not deduce template argument for 'const
std::vector<_Ty,_Alloc> &' from 'const simplexIterator'
1> c:\program files\microsoft visual studio 8\vc\include\vector(1276) : see
declaration of 'std::operator <'
1>c:\program files\microsoft visual studio 8\vc\include\functional(143) :
error C2784: 'bool std::operator <(const std::vector<_Ty,_Alloc> &,const
std::vector<_Ty,_Alloc> &)' : could not deduce template argument for 'const
std::vector<_Ty,_Alloc> &' from 'const simplexIterator'
1> c:\program files\microsoft visual studio 8\vc\include\vector(1276) : see
declaration of 'std::operator <'
1>c:\program files\microsoft visual studio 8\vc\include\functional(143) :
error C2784: 'bool std::operator <(const std::vector<_Ty,_Alloc> &,const
std::vector<_Ty,_Alloc> &)' : could not deduce template argument for 'const
std::vector<_Ty,_Alloc> &' from 'const simplexIterator'
1> c:\program files\microsoft visual studio 8\vc\include\vector(1276) : see
declaration of 'std::operator <'
1>c:\program files\microsoft visual studio 8\vc\include\functional(143) :
error C2784: 'bool std::operator <(const std::_Tree<_Traits> &,const
std::_Tree<_Traits> &)' : could not deduce template argument for 'const
std::_Tree<_Traits> &' from 'const simplexIterator'
1> c:\program files\microsoft visual studio 8\vc\include\xtree(1372) : see
declaration of 'std::operator <'
1>c:\program files\microsoft visual studio 8\vc\include\functional(143) :
error C2784: 'bool std::operator <(const std::_Tree<_Traits> &,const
std::_Tree<_Traits> &)' : could not deduce template argument for 'const
std::_Tree<_Traits> &' from 'const simplexIterator'
1> c:\program files\microsoft visual studio 8\vc\include\xtree(1372) : see
declaration of 'std::operator <'
1>c:\program files\microsoft visual studio 8\vc\include\functional(143) :
error C2784: 'bool std::operator <(const std::_Tree<_Traits> &,const
std::_Tree<_Traits> &)' : could not deduce template argument for 'const
std::_Tree<_Traits> &' from 'const simplexIterator'
1> c:\program files\microsoft visual studio 8\vc\include\xtree(1372) : see
declaration of 'std::operator <'
1>c:\program files\microsoft visual studio 8\vc\include\functional(143) :
error C2784: 'bool std::operator <(const std::_Tree<_Traits> &,const
std::_Tree<_Traits> &)' : could not deduce template argument for 'const
std::_Tree<_Traits> &' from 'const simplexIterator'
1> c:\program files\microsoft visual studio 8\vc\include\xtree(1372) : see
declaration of 'std::operator <'
1>c:\program files\microsoft visual studio 8\vc\include\functional(143) :
error C2784: 'bool std::operator <(const
std::basic_string<_Elem,_Traits,_Alloc> &,const _Elem *)' : could not deduce
template argument for 'const std::basic_string<_Elem,_Traits,_Alloc> &' from
'const simplexIterator'
1> c:\program files\microsoft visual studio 8\vc\include\string(151) : see
declaration of 'std::operator <'
1>c:\program files\microsoft visual studio 8\vc\include\functional(143) :
error C2784: 'bool std::operator <(const
std::basic_string<_Elem,_Traits,_Alloc> &,const _Elem *)' : could not deduce
template argument for 'const std::basic_string<_Elem,_Traits,_Alloc> &' from
'const simplexIterator'
1> c:\program files\microsoft visual studio 8\vc\include\string(151) : see
declaration of 'std::operator <'
1>c:\program files\microsoft visual studio 8\vc\include\functional(143) :
error C2784: 'bool std::operator <(const
std::basic_string<_Elem,_Traits,_Alloc> &,const _Elem *)' : could not deduce
template argument for 'const std::basic_string<_Elem,_Traits,_Alloc> &' from
'const simplexIterator'
1> c:\program files\microsoft visual studio 8\vc\include\string(151) : see
declaration of 'std::operator <'
1>c:\program files\microsoft visual studio 8\vc\include\functional(143) :
error C2784: 'bool std::operator <(const
std::basic_string<_Elem,_Traits,_Alloc> &,const _Elem *)' : could not deduce
template argument for 'const std::basic_string<_Elem,_Traits,_Alloc> &' from
'const simplexIterator'
1> c:\program files\microsoft visual studio 8\vc\include\string(151) : see
declaration of 'std::operator <'
1>c:\program files\microsoft visual studio 8\vc\include\functional(143) :
error C2784: 'bool std::operator <(const _Elem *,const
std::basic_string<_Elem,_Traits,_Alloc> &)' : could not deduce template
argument for 'const _Elem *' from 'const simplexIterator'
1> c:\program files\microsoft visual studio 8\vc\include\string(141) : see
declaration of 'std::operator <'
1>c:\program files\microsoft visual studio 8\vc\include\functional(143) :
error C2784: 'bool std::operator <(const
std::basic_string<_Elem,_Traits,_Alloc> &,const
std::basic_string<_Elem,_Traits,_Alloc> &)' : could not deduce template
argument for 'const std::basic_string<_Elem,_Traits,_Alloc> &' from 'const
simplexIterator'
1> c:\program files\microsoft visual studio 8\vc\include\string(131) : see
declaration of 'std::operator <'
1>c:\program files\microsoft visual studio 8\vc\include\functional(143) :
error C2784: 'bool std::operator <(const
std::basic_string<_Elem,_Traits,_Alloc> &,const
std::basic_string<_Elem,_Traits,_Alloc> &)' : could not deduce template
argument for 'const std::basic_string<_Elem,_Traits,_Alloc> &' from 'const
simplexIterator'
1> c:\program files\microsoft visual studio 8\vc\include\string(131) : see
declaration of 'std::operator <'
1>c:\program files\microsoft visual studio 8\vc\include\functional(143) :
error C2784: 'bool std::operator <(const
std::basic_string<_Elem,_Traits,_Alloc> &,const
std::basic_string<_Elem,_Traits,_Alloc> &)' : could not deduce template
argument for 'const std::basic_string<_Elem,_Traits,_Alloc> &' from 'const
simplexIterator'
1> c:\program files\microsoft visual studio 8\vc\include\string(131) : see
declaration of 'std::operator <'
1>c:\program files\microsoft visual studio 8\vc\include\functional(143) :
error C2784: 'bool std::operator <(const
std::basic_string<_Elem,_Traits,_Alloc> &,const
std::basic_string<_Elem,_Traits,_Alloc> &)' : could not deduce template
argument for 'const std::basic_string<_Elem,_Traits,_Alloc> &' from 'const
simplexIterator'
1> c:\program files\microsoft visual studio 8\vc\include\string(131) : see
declaration of 'std::operator <'
1>c:\program files\microsoft visual studio 8\vc\include\functional(143) :
error C2784: 'bool std::operator <(const std::reverse_iterator<_RanIt>
&,const std::reverse_iterator<_RanIt2> &)' : could not deduce template
argument for 'const std::reverse_iterator<_RanIt> &' from 'const
simplexIterator'
1> c:\program files\microsoft visual studio 8\vc\include\xutility(1842) :
see declaration of 'std::operator <'
1>c:\program files\microsoft visual studio 8\vc\include\functional(143) :
error C2784: 'bool std::operator <(const std::reverse_iterator<_RanIt>
&,const std::reverse_iterator<_RanIt2> &)' : could not deduce template
argument for 'const std::reverse_iterator<_RanIt> &' from 'const
simplexIterator'
1> c:\program files\microsoft visual studio 8\vc\include\xutility(1842) :
see declaration of 'std::operator <'
1>c:\program files\microsoft visual studio 8\vc\include\functional(143) :
error C2784: 'bool std::operator <(const std::reverse_iterator<_RanIt>
&,const std::reverse_iterator<_RanIt2> &)' : could not deduce template
argument for 'const std::reverse_iterator<_RanIt> &' from 'const
simplexIterator'
1> c:\program files\microsoft visual studio 8\vc\include\xutility(1842) :
see declaration of 'std::operator <'
1>c:\program files\microsoft visual studio 8\vc\include\functional(143) :
error C2784: 'bool std::operator <(const std::reverse_iterator<_RanIt>
&,const std::reverse_iterator<_RanIt2> &)' : could not deduce template
argument for 'const std::reverse_iterator<_RanIt> &' from 'const
simplexIterator'
1> c:\program files\microsoft visual studio 8\vc\include\xutility(1842) :
see declaration of 'std::operator <'
1>c:\program files\microsoft visual studio 8\vc\include\functional(143) :
error C2784: 'bool std::operator <(const std::pair<_Ty1,_Ty2> &,const
std::pair<_Ty1,_Ty2> &)' : could not deduce template argument for 'const
std::pair<_Ty1,_Ty2> &' from 'const simplexIterator'
1> c:\program files\microsoft visual studio 8\vc\include\utility(76) : see
declaration of 'std::operator <'
1>c:\program files\microsoft visual studio 8\vc\include\functional(143) :
error C2784: 'bool std::operator <(const std::pair<_Ty1,_Ty2> &,const
std::pair<_Ty1,_Ty2> &)' : could not deduce template argument for 'const
std::pair<_Ty1,_Ty2> &' from 'const simplexIterator'
1> c:\program files\microsoft visual studio 8\vc\include\utility(76) : see
declaration of 'std::operator <'
1>c:\program files\microsoft visual studio 8\vc\include\functional(143) :
error C2784: 'bool std::operator <(const std::pair<_Ty1,_Ty2> &,const
std::pair<_Ty1,_Ty2> &)' : could not deduce template argument for 'const
std::pair<_Ty1,_Ty2> &' from 'const simplexIterator'
1> c:\program files\microsoft visual studio 8\vc\include\utility(76) : see
declaration of 'std::operator <'
1>c:\program files\microsoft visual studio 8\vc\include\functional(143) :
error C2784: 'bool std::operator <(const std::pair<_Ty1,_Ty2> &,const
std::pair<_Ty1,_Ty2> &)' : could not deduce template argument for 'const
std::pair<_Ty1,_Ty2> &' from 'const simplexIterator'
1> c:\program files\microsoft visual studio 8\vc\include\utility(76) : see
declaration of 'std::operator <'
1>c:\program files\microsoft visual studio 8\vc\include\functional(143) :
error C2676: binary '<' : 'const simplexIterator' does not define this
operator or a conversion to a type acceptable to the predefined operator
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
Désolé pour la laideur des messages d'erreur ;o)
Est-ce normal ?
Merci d'avance...
Cette action est irreversible, confirmez la suppression du commentaire ?
Signaler le commentaire
Veuillez sélectionner un problème
Nudité
Violence
Harcèlement
Fraude
Vente illégale
Discours haineux
Terrorisme
Autre
Clement
"Clement" a écrit dans le message de news: 451a9c1a$0$852$
Bonjour,
Voilà, j'ai un petit problème avec VC2005 que je ne rencontre pas avec VC2003.net (je sais qu'ici, on ne parle pas des compilateurs, mais je voudrais juste savoir si mon code est à la norme ou pas). Voici le morceau de code en cause :
Finalement, j'ai choisi de définir une class pour la comparaison :
et mettre : std::multiset<simplexIterator, simplexIteratorCmp> m_children;
Et voilà, ça marche bien ! Mais je serais curieux de comprendre tout de même le problème... A+
"Clement" <a@a.a.invalid> a écrit dans le message de news:
451a9c1a$0$852$636a55ce@news.free.fr...
Bonjour,
Voilà, j'ai un petit problème avec VC2005 que je ne rencontre pas avec
VC2003.net (je sais qu'ici, on ne parle pas des compilateurs, mais je
voudrais juste savoir si mon code est à la norme ou pas).
Voici le morceau de code en cause :
Finalement, j'ai choisi de définir une class pour la comparaison :
"Clement" a écrit dans le message de news: 451a9c1a$0$852$
Bonjour,
Voilà, j'ai un petit problème avec VC2005 que je ne rencontre pas avec VC2003.net (je sais qu'ici, on ne parle pas des compilateurs, mais je voudrais juste savoir si mon code est à la norme ou pas). Voici le morceau de code en cause :
Finalement, j'ai choisi de définir une class pour la comparaison :
et mettre : std::multiset<simplexIterator, simplexIteratorCmp> m_children;
Et voilà, ça marche bien ! Mais je serais curieux de comprendre tout de même le problème... A+
kanze
Clement wrote:
Voilà, j'ai un petit problème avec VC2005 que je ne rencontre pas avec VC2003.net (je sais qu'ici, on ne parle pas des compilateurs, mais je voudrais juste savoir si mon code est à la norme ou pas).
Le code est illégal. Bien qu'il passera la plupart des compilateurs, il a un comportement indéfini. (Il n'échoue avec g++ que si on démande des options des vérifications supplémentaires des templates.)
Voici le morceau de code en cause :
======================== =====================
#include <set>
class CSimplex; typedef std::set<CSimplex>::iterator simplexIterator;
Et c'est ici que ça coince. Vouloir nommé un type défini dans un template provoque l'instantiation du template. Et la norme est claire : instantier un template dans la norme sur un type incomplet est un comportement indéfini.
Cette ligne suffit à provoquer des erreurs avec g++. Je crois qu'il passe encore avec VC++ 8.0, mais je ne suis pas sûr.
Ici, je suis moins sûr, mais je crois aussi que tu ouvres la porte à des ambiguïtés. Dans ton code, simplexIterator est un typedef pour un std::set<>::iterator. Au minimum, std::set<>::iterator est un itérateur bi-directionnel, et dans tel cas, il n'y a pas de problème (je crois). Je crois, en revanche, qu'une implémentation a le droit de le faire un type d'itérateur plus performant, c-à-d un itérateur à accès aléatoire ; si elle le fait, l'opérateur < en est déjà défini dans la norme.
{ return *s1 < *s2; }
======================== =====================
Dans une des fonctions membres de la classe CSimplex, j'appelle m_children.insert(s) où s est un simplexIterator. J'obtiens alors les erreurs de compilation suivantes :
Que je n'arrive pas trop à comprendre (mais c'est souvent le cas quand l'erreur concerne un template).
Une chose que tu pourrais essayer, c'est d'instantier les multiset avec un deuxième paramètre, un objet fonctionnel que tu aurais écris. Mais à la longue, je crois que tu vas être quitte à une réstructuration du code, pour éviter l'utilisation du std::set<CSimplex>::iterator avant la fin de la définition de la classe CSimplex. (Peut-être l'idiome du par-feu de compilation, ou pimpl, pourrait t'y aider.)
-- 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
Clement wrote:
Voilà, j'ai un petit problème avec VC2005 que je ne rencontre
pas avec VC2003.net (je sais qu'ici, on ne parle pas des
compilateurs, mais je voudrais juste savoir si mon code est à
la norme ou pas).
Le code est illégal. Bien qu'il passera la plupart des
compilateurs, il a un comportement indéfini. (Il n'échoue avec
g++ que si on démande des options des vérifications
supplémentaires des templates.)
Voici le morceau de code en cause :
======================== =====================
#include <set>
class CSimplex;
typedef std::set<CSimplex>::iterator simplexIterator;
Et c'est ici que ça coince. Vouloir nommé un type défini dans un
template provoque l'instantiation du template. Et la norme est
claire : instantier un template dans la norme sur un type
incomplet est un comportement indéfini.
Cette ligne suffit à provoquer des erreurs avec g++. Je crois
qu'il passe encore avec VC++ 8.0, mais je ne suis pas sûr.
Ici, je suis moins sûr, mais je crois aussi que tu ouvres la
porte à des ambiguïtés. Dans ton code, simplexIterator est un
typedef pour un std::set<>::iterator. Au minimum,
std::set<>::iterator est un itérateur bi-directionnel, et dans
tel cas, il n'y a pas de problème (je crois). Je crois, en
revanche, qu'une implémentation a le droit de le faire un type
d'itérateur plus performant, c-à-d un itérateur à accès
aléatoire ; si elle le fait, l'opérateur < en est déjà défini
dans la norme.
{
return *s1 < *s2;
}
======================== =====================
Dans une des fonctions membres de la classe CSimplex, j'appelle
m_children.insert(s) où s est un simplexIterator.
J'obtiens alors les erreurs de compilation suivantes :
Que je n'arrive pas trop à comprendre (mais c'est souvent le cas
quand l'erreur concerne un template).
Une chose que tu pourrais essayer, c'est d'instantier les
multiset avec un deuxième paramètre, un objet fonctionnel que tu
aurais écris. Mais à la longue, je crois que tu vas être quitte
à une réstructuration du code, pour éviter l'utilisation du
std::set<CSimplex>::iterator avant la fin de la définition de la
classe CSimplex. (Peut-être l'idiome du par-feu de compilation,
ou pimpl, pourrait t'y aider.)
--
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
Voilà, j'ai un petit problème avec VC2005 que je ne rencontre pas avec VC2003.net (je sais qu'ici, on ne parle pas des compilateurs, mais je voudrais juste savoir si mon code est à la norme ou pas).
Le code est illégal. Bien qu'il passera la plupart des compilateurs, il a un comportement indéfini. (Il n'échoue avec g++ que si on démande des options des vérifications supplémentaires des templates.)
Voici le morceau de code en cause :
======================== =====================
#include <set>
class CSimplex; typedef std::set<CSimplex>::iterator simplexIterator;
Et c'est ici que ça coince. Vouloir nommé un type défini dans un template provoque l'instantiation du template. Et la norme est claire : instantier un template dans la norme sur un type incomplet est un comportement indéfini.
Cette ligne suffit à provoquer des erreurs avec g++. Je crois qu'il passe encore avec VC++ 8.0, mais je ne suis pas sûr.
Ici, je suis moins sûr, mais je crois aussi que tu ouvres la porte à des ambiguïtés. Dans ton code, simplexIterator est un typedef pour un std::set<>::iterator. Au minimum, std::set<>::iterator est un itérateur bi-directionnel, et dans tel cas, il n'y a pas de problème (je crois). Je crois, en revanche, qu'une implémentation a le droit de le faire un type d'itérateur plus performant, c-à-d un itérateur à accès aléatoire ; si elle le fait, l'opérateur < en est déjà défini dans la norme.
{ return *s1 < *s2; }
======================== =====================
Dans une des fonctions membres de la classe CSimplex, j'appelle m_children.insert(s) où s est un simplexIterator. J'obtiens alors les erreurs de compilation suivantes :
Que je n'arrive pas trop à comprendre (mais c'est souvent le cas quand l'erreur concerne un template).
Une chose que tu pourrais essayer, c'est d'instantier les multiset avec un deuxième paramètre, un objet fonctionnel que tu aurais écris. Mais à la longue, je crois que tu vas être quitte à une réstructuration du code, pour éviter l'utilisation du std::set<CSimplex>::iterator avant la fin de la définition de la classe CSimplex. (Peut-être l'idiome du par-feu de compilation, ou pimpl, pourrait t'y aider.)
-- 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
Clement
Bonjour,
Merci pour ces conseils. J'ai posté la seconde solution que j'utilise maintenant dans mon précédent message. Il n'y a plus l'ambiguïté du inline bool operator<(const simplexIterator &s1, const simplexIterator &s2) mais j'ai toujours "typedef std::set<CSimplex>::iterator simplexIterator;".
En fait, je souhaite tout simplement faire ceci (c'est simplifié mais ca suffit) : 1. J'ai deux "set" : un rempli avec des CSimplex de dimension 0 (des points - la dimension est un paramètre de la classe CSimplex) et un rempli avec des CSimplex de dimension 1 (des segments). 2. Dans les CSimplex de dimension 1 (segments), je souhaite stocker deux itérateurs vers les deux points du segment contenus dans l'autre "set". J'utilise un multiset car je veux que ces itérateurs soient triées et non uniques. 3. De même, les points pointent vers leurs segments parents... etc...
Comment faire autrement qu'avec des itérateurs ? Le problème vient du fait qu'un CSimplex contient des iterateurs vers d'autres CSimplex. Suis-je forcé d'utilisé des pointeurs vers CSimplex dans mes multiset ?
Merci encore. Clément.
Bonjour,
Merci pour ces conseils. J'ai posté la seconde solution que j'utilise
maintenant dans mon précédent message.
Il n'y a plus l'ambiguïté du inline bool operator<(const simplexIterator
&s1, const simplexIterator &s2) mais j'ai toujours "typedef
std::set<CSimplex>::iterator simplexIterator;".
En fait, je souhaite tout simplement faire ceci (c'est simplifié mais ca
suffit) :
1. J'ai deux "set" : un rempli avec des CSimplex de dimension 0 (des
points - la dimension est un paramètre de la classe CSimplex) et un rempli
avec des CSimplex de dimension 1 (des segments).
2. Dans les CSimplex de dimension 1 (segments), je souhaite stocker deux
itérateurs vers les deux points du segment contenus dans l'autre "set".
J'utilise un multiset car je veux que ces itérateurs soient triées et non
uniques.
3. De même, les points pointent vers leurs segments parents... etc...
Comment faire autrement qu'avec des itérateurs ? Le problème vient du fait
qu'un CSimplex contient des iterateurs vers d'autres CSimplex. Suis-je forcé
d'utilisé des pointeurs vers CSimplex dans mes multiset ?
Merci pour ces conseils. J'ai posté la seconde solution que j'utilise maintenant dans mon précédent message. Il n'y a plus l'ambiguïté du inline bool operator<(const simplexIterator &s1, const simplexIterator &s2) mais j'ai toujours "typedef std::set<CSimplex>::iterator simplexIterator;".
En fait, je souhaite tout simplement faire ceci (c'est simplifié mais ca suffit) : 1. J'ai deux "set" : un rempli avec des CSimplex de dimension 0 (des points - la dimension est un paramètre de la classe CSimplex) et un rempli avec des CSimplex de dimension 1 (des segments). 2. Dans les CSimplex de dimension 1 (segments), je souhaite stocker deux itérateurs vers les deux points du segment contenus dans l'autre "set". J'utilise un multiset car je veux que ces itérateurs soient triées et non uniques. 3. De même, les points pointent vers leurs segments parents... etc...
Comment faire autrement qu'avec des itérateurs ? Le problème vient du fait qu'un CSimplex contient des iterateurs vers d'autres CSimplex. Suis-je forcé d'utilisé des pointeurs vers CSimplex dans mes multiset ?
Merci encore. Clément.
kanze
Clement wrote:
Merci pour ces conseils. J'ai posté la seconde solution que j'utilise maintenant dans mon précédent message.
Il n'y a plus l'ambiguïté du inline bool operator<(const simplexItera tor &s1, const simplexIterator &s2) mais j'ai toujours "typedef std::set<CSimplex>::iterator simplexIterator;".
Ce qui veut dire que ça ne marcherait pas avec g++ quand la vérification des concepts est active. Ni, peut-être, avec la prochaine version de VC++.
En fait, je souhaite tout simplement faire ceci (c'est simplifié mais ca suffit) :
1. J'ai deux "set" : un rempli avec des CSimplex de dimension 0 (des points - la dimension est un paramètre de la classe CSimplex) et un rem pli avec des CSimplex de dimension 1 (des segments). 2. Dans les CSimplex de dimension 1 (segments), je souhaite stocker deux itérateurs vers les deux points du segment contenus dans l'autre "set". J'utilise un multiset car je veux que ces itérateurs soient triées et non uniques. 3. De même, les points pointent vers leurs segments parents... etc...
Comment faire autrement qu'avec des itérateurs ?
Plusieurs solutions sont possibles :
-- La plus simple, c'est probablement simplement d'utiliser l'idiome du pare-feu de compilation, autrement dit de pimpl. Ça évite systèmatiquement toute nécessité d'une déclaration de ce qu'il y a dans ton implémentation. Et ta classe me semble assez lourde pour que l'indirection supplémentaire ne fasse pas de différence.
-- Sinon, tu utilises les pointeurs à des CSimplex, plutôt que des itérateurs. std::set garantit que les pointeurs à un élément soient valides aussi longtemps que l'élément est dans la collection.
En passant, est-ce que tu es sûr que tu veux un std::set< CSimplex >, et non un std::set< CSimplex* > ? Mettre un élément dans une collection impose des copies, et la copie d'un objet avec deux multiset n'est pas forcément bon marché. D'autant plus que si l'objet a des parents et des enfants, il y a bien des chances que son identité soit importante. En plus, si tu utilises des pointeurs partout, tu pourrais changer plus tard pour un std::vector, ou que sais-je, avec moins de problèmes.
En général, je me méfie de l'utilisation des itérateurs autrement que pour l'itération. Selon le type de la collection, ils ont une validité plus ou moins délicate. La même chose vaut pour les adresses des objets dans une collection ; la collection est libre de les copier, et de se servir de la copie, dans certains cas. Alors, la navigation ne se fait pas entre des éléments d'une collection ; s'il faut naviguer entre des objets, on met des pointeurs à ces objets dans les collections, et non les objets même.
Le problème vient du fait qu'un CSimplex contient des iterateurs vers d'autres CSimplex. Suis-je forcé d'utilisé des pointeurs vers CSimplex dans mes multiset ?
C'est ce que je ferais, de toutes façons. Je me servirais probablement aussi de l'idiome du pare-feu de la compilation, pour que les utilisateurs de ma classe n'aient pas les temps de compilation exagéré à cause de tous les include qui ne les intéressent pas.
-- 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
Clement wrote:
Merci pour ces conseils. J'ai posté la seconde solution que
j'utilise maintenant dans mon précédent message.
Il n'y a plus l'ambiguïté du inline bool operator<(const simplexItera tor
&s1, const simplexIterator &s2) mais j'ai toujours "typedef
std::set<CSimplex>::iterator simplexIterator;".
Ce qui veut dire que ça ne marcherait pas avec g++ quand la
vérification des concepts est active. Ni, peut-être, avec la
prochaine version de VC++.
En fait, je souhaite tout simplement faire ceci (c'est
simplifié mais ca suffit) :
1. J'ai deux "set" : un rempli avec des CSimplex de dimension 0 (des
points - la dimension est un paramètre de la classe CSimplex) et un rem pli
avec des CSimplex de dimension 1 (des segments).
2. Dans les CSimplex de dimension 1 (segments), je souhaite stocker deux
itérateurs vers les deux points du segment contenus dans l'autre "set".
J'utilise un multiset car je veux que ces itérateurs soient triées et non
uniques.
3. De même, les points pointent vers leurs segments parents... etc...
Comment faire autrement qu'avec des itérateurs ?
Plusieurs solutions sont possibles :
-- La plus simple, c'est probablement simplement d'utiliser
l'idiome du pare-feu de compilation, autrement dit de pimpl.
Ça évite systèmatiquement toute nécessité d'une déclaration
de ce qu'il y a dans ton implémentation. Et ta classe me
semble assez lourde pour que l'indirection supplémentaire ne
fasse pas de différence.
-- Sinon, tu utilises les pointeurs à des CSimplex, plutôt que
des itérateurs. std::set garantit que les pointeurs à un
élément soient valides aussi longtemps que l'élément est
dans la collection.
En passant, est-ce que tu es sûr que tu veux un
std::set< CSimplex >, et non un std::set< CSimplex* > ?
Mettre un élément dans une collection impose des copies, et
la copie d'un objet avec deux multiset n'est pas forcément
bon marché. D'autant plus que si l'objet a des parents et
des enfants, il y a bien des chances que son identité soit
importante. En plus, si tu utilises des pointeurs partout,
tu pourrais changer plus tard pour un std::vector, ou que
sais-je, avec moins de problèmes.
En général, je me méfie de l'utilisation des itérateurs
autrement que pour l'itération. Selon le type de la
collection, ils ont une validité plus ou moins délicate. La
même chose vaut pour les adresses des objets dans une
collection ; la collection est libre de les copier, et de
se servir de la copie, dans certains cas. Alors, la
navigation ne se fait pas entre des éléments d'une
collection ; s'il faut naviguer entre des objets, on met
des pointeurs à ces objets dans les collections, et non les
objets même.
Le problème vient du fait qu'un CSimplex contient des
iterateurs vers d'autres CSimplex. Suis-je forcé d'utilisé des
pointeurs vers CSimplex dans mes multiset ?
C'est ce que je ferais, de toutes façons. Je me servirais
probablement aussi de l'idiome du pare-feu de la compilation,
pour que les utilisateurs de ma classe n'aient pas les temps de
compilation exagéré à cause de tous les include qui ne les
intéressent pas.
--
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 pour ces conseils. J'ai posté la seconde solution que j'utilise maintenant dans mon précédent message.
Il n'y a plus l'ambiguïté du inline bool operator<(const simplexItera tor &s1, const simplexIterator &s2) mais j'ai toujours "typedef std::set<CSimplex>::iterator simplexIterator;".
Ce qui veut dire que ça ne marcherait pas avec g++ quand la vérification des concepts est active. Ni, peut-être, avec la prochaine version de VC++.
En fait, je souhaite tout simplement faire ceci (c'est simplifié mais ca suffit) :
1. J'ai deux "set" : un rempli avec des CSimplex de dimension 0 (des points - la dimension est un paramètre de la classe CSimplex) et un rem pli avec des CSimplex de dimension 1 (des segments). 2. Dans les CSimplex de dimension 1 (segments), je souhaite stocker deux itérateurs vers les deux points du segment contenus dans l'autre "set". J'utilise un multiset car je veux que ces itérateurs soient triées et non uniques. 3. De même, les points pointent vers leurs segments parents... etc...
Comment faire autrement qu'avec des itérateurs ?
Plusieurs solutions sont possibles :
-- La plus simple, c'est probablement simplement d'utiliser l'idiome du pare-feu de compilation, autrement dit de pimpl. Ça évite systèmatiquement toute nécessité d'une déclaration de ce qu'il y a dans ton implémentation. Et ta classe me semble assez lourde pour que l'indirection supplémentaire ne fasse pas de différence.
-- Sinon, tu utilises les pointeurs à des CSimplex, plutôt que des itérateurs. std::set garantit que les pointeurs à un élément soient valides aussi longtemps que l'élément est dans la collection.
En passant, est-ce que tu es sûr que tu veux un std::set< CSimplex >, et non un std::set< CSimplex* > ? Mettre un élément dans une collection impose des copies, et la copie d'un objet avec deux multiset n'est pas forcément bon marché. D'autant plus que si l'objet a des parents et des enfants, il y a bien des chances que son identité soit importante. En plus, si tu utilises des pointeurs partout, tu pourrais changer plus tard pour un std::vector, ou que sais-je, avec moins de problèmes.
En général, je me méfie de l'utilisation des itérateurs autrement que pour l'itération. Selon le type de la collection, ils ont une validité plus ou moins délicate. La même chose vaut pour les adresses des objets dans une collection ; la collection est libre de les copier, et de se servir de la copie, dans certains cas. Alors, la navigation ne se fait pas entre des éléments d'une collection ; s'il faut naviguer entre des objets, on met des pointeurs à ces objets dans les collections, et non les objets même.
Le problème vient du fait qu'un CSimplex contient des iterateurs vers d'autres CSimplex. Suis-je forcé d'utilisé des pointeurs vers CSimplex dans mes multiset ?
C'est ce que je ferais, de toutes façons. Je me servirais probablement aussi de l'idiome du pare-feu de la compilation, pour que les utilisateurs de ma classe n'aient pas les temps de compilation exagéré à cause de tous les include qui ne les intéressent pas.
-- 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
kanze
Clement wrote:
"Clement" a écrit dans le message de news: 451a9c1a$0$852$
Voilà, j'ai un petit problème avec VC2005 que je ne rencontre pas avec VC2003.net (je sais qu'ici, on ne parle pas des compilateurs, mais je voudrais juste savoir si mon code est à la norme ou pas). Voici le morceau de code en cause :
Finalement, j'ai choisi de définir une class pour la comparaison :
class simplexIteratorCmp { public: bool operator()(const simplexIterator & s1, const simplexIterator & s 2) const; };
et mettre : std::multiset<simplexIterator, simplexIteratorCmp> m_children;
Et voilà, ça marche bien ! Mais je serais curieux de comprendre tout de même le problème...
Il y a deux possibilités (parce que je ne crois pas qu'il vient du comportement indéfini dans le typedef) : ou bien, il y a une utilisation du type quelque part dans une contexte undéductible -- je ne crois pas, mais les règles à cet égard sont tellement complexes que je n'arrive pas à les comprendre --, ou bien, il y une erreur dans le compilateur Microsoft.
comme j'ai dit dans un autre posting, à mon avis, tu ferais mieux de remplacer déjà ton std::set< CSimplex > par un std::set< CSimplex* > (qui n'exige pas la définition complète de CSimplex, puisque le template ne connaît que des pointeurs). De même pour les multiset qui servent à la navigation.
-- 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
Clement wrote:
"Clement" <a@a.a.invalid> a écrit dans le message de news:
451a9c1a$0$852$636a55ce@news.free.fr...
Voilà, j'ai un petit problème avec VC2005 que je ne
rencontre pas avec VC2003.net (je sais qu'ici, on ne parle
pas des compilateurs, mais je voudrais juste savoir si mon
code est à la norme ou pas). Voici le morceau de code en
cause :
Finalement, j'ai choisi de définir une class pour la comparaison :
class simplexIteratorCmp
{
public:
bool operator()(const simplexIterator & s1, const simplexIterator & s 2)
const;
};
et mettre :
std::multiset<simplexIterator, simplexIteratorCmp> m_children;
Et voilà, ça marche bien !
Mais je serais curieux de comprendre tout de même le problème...
Il y a deux possibilités (parce que je ne crois pas qu'il vient
du comportement indéfini dans le typedef) : ou bien, il y a une
utilisation du type quelque part dans une contexte
undéductible -- je ne crois pas, mais les règles à cet égard
sont tellement complexes que je n'arrive pas à les
comprendre --, ou bien, il y une erreur dans le compilateur
Microsoft.
comme j'ai dit dans un autre posting, à mon avis, tu ferais
mieux de remplacer déjà ton std::set< CSimplex > par un
std::set< CSimplex* > (qui n'exige pas la définition complète de
CSimplex, puisque le template ne connaît que des pointeurs). De
même pour les multiset qui servent à la navigation.
--
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
"Clement" a écrit dans le message de news: 451a9c1a$0$852$
Voilà, j'ai un petit problème avec VC2005 que je ne rencontre pas avec VC2003.net (je sais qu'ici, on ne parle pas des compilateurs, mais je voudrais juste savoir si mon code est à la norme ou pas). Voici le morceau de code en cause :
Finalement, j'ai choisi de définir une class pour la comparaison :
class simplexIteratorCmp { public: bool operator()(const simplexIterator & s1, const simplexIterator & s 2) const; };
et mettre : std::multiset<simplexIterator, simplexIteratorCmp> m_children;
Et voilà, ça marche bien ! Mais je serais curieux de comprendre tout de même le problème...
Il y a deux possibilités (parce que je ne crois pas qu'il vient du comportement indéfini dans le typedef) : ou bien, il y a une utilisation du type quelque part dans une contexte undéductible -- je ne crois pas, mais les règles à cet égard sont tellement complexes que je n'arrive pas à les comprendre --, ou bien, il y une erreur dans le compilateur Microsoft.
comme j'ai dit dans un autre posting, à mon avis, tu ferais mieux de remplacer déjà ton std::set< CSimplex > par un std::set< CSimplex* > (qui n'exige pas la définition complète de CSimplex, puisque le template ne connaît que des pointeurs). De même pour les multiset qui servent à la navigation.
-- 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
Clement
"kanze" a écrit dans le message news:...
Clement wrote:
Ce qui veut dire que ça ne marcherait pas avec g++ quand la vérification des concepts est active. Ni, peut-être, avec la prochaine version de VC++.
Ok, je vais donc changer ça...
Plusieurs solutions sont possibles :
-- La plus simple, c'est probablement simplement d'utiliser l'idiome du pare-feu de compilation, autrement dit de pimpl. Ça évite systèmatiquement toute nécessité d'une déclaration de ce qu'il y a dans ton implémentation. Et ta classe me semble assez lourde pour que l'indirection supplémentaire ne fasse pas de différence.
En effet, c'est une bonne idée.
-- Sinon, tu utilises les pointeurs à des CSimplex, plutôt que des itérateurs. std::set garantit que les pointeurs à un élément soient valides aussi longtemps que l'élément est dans la collection.
Oui j'y avais pensé mais ça m'oblige à faire des new et des delete...
En passant, est-ce que tu es sûr que tu veux un std::set< CSimplex >, et non un std::set< CSimplex* > ? Mettre un élément dans une collection impose des copies, et la copie d'un objet avec deux multiset n'est pas forcément bon marché. D'autant plus que si l'objet a des parents et des enfants, il y a bien des chances que son identité soit importante. En plus, si tu utilises des pointeurs partout, tu pourrais changer plus tard pour un std::vector, ou que sais-je, avec moins de problèmes.
C'est vrai qu'à bien y réfléchir, je vais sûrement utiliser cette solution.
En général, je me méfie de l'utilisation des itérateurs autrement que pour l'itération. Selon le type de la collection, ils ont une validité plus ou moins délicate. La même chose vaut pour les adresses des objets dans une collection ; la collection est libre de les copier, et de se servir de la copie, dans certains cas. Alors, la navigation ne se fait pas entre des éléments d'une collection ; s'il faut naviguer entre des objets, on met des pointeurs à ces objets dans les collections, et non les objets même.
Oui, les set garantissent des iterateur toujours valides, donc j'avais pensé que ce serait plus "C++" d'utiliser des itérateurs... Apparemment ce n'était pas une bonne idée ;o)
En tout cas, merci beaucoup pour ta réponse très complète ! Clément.
"kanze" a écrit dans le message
news:1159456086.408870.294080@e3g2000cwe.googlegroups.com>...
Clement wrote:
Ce qui veut dire que ça ne marcherait pas avec g++ quand la
vérification des concepts est active. Ni, peut-être, avec la
prochaine version de VC++.
Ok, je vais donc changer ça...
Plusieurs solutions sont possibles :
-- La plus simple, c'est probablement simplement d'utiliser
l'idiome du pare-feu de compilation, autrement dit de pimpl.
Ça évite systèmatiquement toute nécessité d'une déclaration
de ce qu'il y a dans ton implémentation. Et ta classe me
semble assez lourde pour que l'indirection supplémentaire ne
fasse pas de différence.
En effet, c'est une bonne idée.
-- Sinon, tu utilises les pointeurs à des CSimplex, plutôt que
des itérateurs. std::set garantit que les pointeurs à un
élément soient valides aussi longtemps que l'élément est
dans la collection.
Oui j'y avais pensé mais ça m'oblige à faire des new et des delete...
En passant, est-ce que tu es sûr que tu veux un
std::set< CSimplex >, et non un std::set< CSimplex* > ?
Mettre un élément dans une collection impose des copies, et
la copie d'un objet avec deux multiset n'est pas forcément
bon marché. D'autant plus que si l'objet a des parents et
des enfants, il y a bien des chances que son identité soit
importante. En plus, si tu utilises des pointeurs partout,
tu pourrais changer plus tard pour un std::vector, ou que
sais-je, avec moins de problèmes.
C'est vrai qu'à bien y réfléchir, je vais sûrement utiliser cette solution.
En général, je me méfie de l'utilisation des itérateurs
autrement que pour l'itération. Selon le type de la
collection, ils ont une validité plus ou moins délicate. La
même chose vaut pour les adresses des objets dans une
collection ; la collection est libre de les copier, et de
se servir de la copie, dans certains cas. Alors, la
navigation ne se fait pas entre des éléments d'une
collection ; s'il faut naviguer entre des objets, on met
des pointeurs à ces objets dans les collections, et non les
objets même.
Oui, les set garantissent des iterateur toujours valides, donc j'avais pensé
que ce serait plus "C++" d'utiliser des itérateurs...
Apparemment ce n'était pas une bonne idée ;o)
En tout cas, merci beaucoup pour ta réponse très complète !
Clément.
Ce qui veut dire que ça ne marcherait pas avec g++ quand la vérification des concepts est active. Ni, peut-être, avec la prochaine version de VC++.
Ok, je vais donc changer ça...
Plusieurs solutions sont possibles :
-- La plus simple, c'est probablement simplement d'utiliser l'idiome du pare-feu de compilation, autrement dit de pimpl. Ça évite systèmatiquement toute nécessité d'une déclaration de ce qu'il y a dans ton implémentation. Et ta classe me semble assez lourde pour que l'indirection supplémentaire ne fasse pas de différence.
En effet, c'est une bonne idée.
-- Sinon, tu utilises les pointeurs à des CSimplex, plutôt que des itérateurs. std::set garantit que les pointeurs à un élément soient valides aussi longtemps que l'élément est dans la collection.
Oui j'y avais pensé mais ça m'oblige à faire des new et des delete...
En passant, est-ce que tu es sûr que tu veux un std::set< CSimplex >, et non un std::set< CSimplex* > ? Mettre un élément dans une collection impose des copies, et la copie d'un objet avec deux multiset n'est pas forcément bon marché. D'autant plus que si l'objet a des parents et des enfants, il y a bien des chances que son identité soit importante. En plus, si tu utilises des pointeurs partout, tu pourrais changer plus tard pour un std::vector, ou que sais-je, avec moins de problèmes.
C'est vrai qu'à bien y réfléchir, je vais sûrement utiliser cette solution.
En général, je me méfie de l'utilisation des itérateurs autrement que pour l'itération. Selon le type de la collection, ils ont une validité plus ou moins délicate. La même chose vaut pour les adresses des objets dans une collection ; la collection est libre de les copier, et de se servir de la copie, dans certains cas. Alors, la navigation ne se fait pas entre des éléments d'une collection ; s'il faut naviguer entre des objets, on met des pointeurs à ces objets dans les collections, et non les objets même.
Oui, les set garantissent des iterateur toujours valides, donc j'avais pensé que ce serait plus "C++" d'utiliser des itérateurs... Apparemment ce n'était pas une bonne idée ;o)
En tout cas, merci beaucoup pour ta réponse très complète ! Clément.
kanze
Clement wrote:
"kanze" a écrit dans le message news:...
Clement wrote:
[...]
-- Sinon, tu utilises les pointeurs à des CSimplex, plutôt que des itérateurs. std::set garantit que les pointeurs à un élément soient valides aussi longtemps que l'élément est dans la collection.
Oui j'y avais pensé mais ça m'oblige à faire des new et des delete...
C'est vrai. Mais de l'autre part, tu navigues entre les objets. Ça suppose que les objets ont une identité -- que tu ne peux pas librement remplacer un objet par une copie. Or, si c'est vrai qu'on peut s'en tirer avec std::set<CSimplex>, en faisait bien attention, c'est à mon avis fragile, parce qu'il va à l'encontre de la philosophie générale de la STL : qu'on met des valeurs, qui peuvent être librement copiées, dans les collections, et non des entités. Vue la sémantique apparente de tes objets, j'interdirais même la copie et l'affectation, et alors, évidemment, impossible à les mettre dans une collection quelconque.
A priori, j'ai l'impression que tes objets représentent une graphe. Il se peut qu'il y a des parties que tu n'as pas montré, parce qu'elles n'avaient pas d'importance pour la question, mais si leurs destructeurs ne font que de libéré la mémoire, la solution idéale serait de se servir simplement du collecteur de Boehm ; il faudra toujours des new, pour créer les objets, mais une fois que tu n'y peux plus accéder, ils disparaissent tout seuls ; pas besoin d'un delete. (Pour profiter pleinement du ramasse-miettes, il faudrait modifier la STL un peu. Mais les classes en question, c'est std::vector et std::deque ; il n'y a pas de problème avec des collections basées sur des vertices, genre std::list ou std::set.)
Sinon, et si tu veux que la collection soit le propriétaire final des objets, que leur durée de vie correspond bien à celle de la collection, et que ce soit elle qui les détruit, il existe la solution d'une collection des pointeurs intelligents, des boost::shared_ptr, par exemple. Dans ce cas si, je me démande même si la solution n'est pas d'utiliser les pointeurs bruts à peu près partout sauf dans la collection ; ça donne effectivement les durées de vie que tu as actuellement. Et ça marche même s'il t'arrive des cycles dans la graphe.
En passant, est-ce que tu es sûr que tu veux un std::set< CSimplex >, et non un std::set< CSimplex* > ? Mettre un élément dans une collection impose des copies, et la copie d'un objet avec deux multiset n'est pas forcément bon marché. D'autant plus que si l'objet a des parents et des enfants, il y a bien des chances que son identité soit importante. En plus, si tu utilises des pointeurs partout, tu pourrais changer plus tard pour un std::vector, ou que sais-je, avec moins de problèmes.
C'est vrai qu'à bien y réfléchir, je vais sûrement utiliser cette solution.
Alors, considère aussi l'utilisation du collecteur de Boehm ou de boost::shared_ptr.
En général, je me méfie de l'utilisation des itérateurs autrement que pour l'itération. Selon le type de la collection, ils ont une validité plus ou moins délicate. La même chose vaut pour les adresses des objets dans une collection ; la collection est libre de les copier, et de se servir de la copie, dans certains cas. Alors, la navigation ne se fait pas entre des éléments d'une collection ; s'il faut naviguer entre des objets, on met des pointeurs à ces objets dans les collections, et non les objets même.
Oui, les set garantissent des iterateur toujours valides, donc j'avais pensé que ce serait plus "C++" d'utiliser des itérateurs... Apparemment ce n'était pas une bonne idée ;o)
Les itérateurs sont là pour itérer. Leur nom en dit tout. La force du C++, c'est d'être un langage multi-paradigme. La façon la plus "C++", c'est d'utiliser le paradigme qui convient le mieux à ce qu'on veut faire (plutôt qu'un imposé par le langage).
-- 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
Clement wrote:
"kanze" a écrit dans le message
news:1159456086.408870.294080@e3g2000cwe.googlegroups.com>...
Clement wrote:
[...]
-- Sinon, tu utilises les pointeurs à des CSimplex, plutôt que
des itérateurs. std::set garantit que les pointeurs à un
élément soient valides aussi longtemps que l'élément est
dans la collection.
Oui j'y avais pensé mais ça m'oblige à faire des new et des
delete...
C'est vrai. Mais de l'autre part, tu navigues entre les objets.
Ça suppose que les objets ont une identité -- que tu ne peux
pas librement remplacer un objet par une copie. Or, si c'est
vrai qu'on peut s'en tirer avec std::set<CSimplex>, en faisait
bien attention, c'est à mon avis fragile, parce qu'il va à
l'encontre de la philosophie générale de la STL : qu'on met des
valeurs, qui peuvent être librement copiées, dans les
collections, et non des entités. Vue la sémantique apparente de
tes objets, j'interdirais même la copie et l'affectation, et
alors, évidemment, impossible à les mettre dans une collection
quelconque.
A priori, j'ai l'impression que tes objets représentent une
graphe. Il se peut qu'il y a des parties que tu n'as pas montré,
parce qu'elles n'avaient pas d'importance pour la question, mais
si leurs destructeurs ne font que de libéré la mémoire, la
solution idéale serait de se servir simplement du collecteur de
Boehm ; il faudra toujours des new, pour créer les objets, mais
une fois que tu n'y peux plus accéder, ils disparaissent tout
seuls ; pas besoin d'un delete. (Pour profiter pleinement du
ramasse-miettes, il faudrait modifier la STL un peu. Mais les
classes en question, c'est std::vector et std::deque ; il n'y a
pas de problème avec des collections basées sur des vertices,
genre std::list ou std::set.)
Sinon, et si tu veux que la collection soit le propriétaire
final des objets, que leur durée de vie correspond bien à celle
de la collection, et que ce soit elle qui les détruit, il existe
la solution d'une collection des pointeurs intelligents, des
boost::shared_ptr, par exemple. Dans ce cas si, je me démande
même si la solution n'est pas d'utiliser les pointeurs bruts à
peu près partout sauf dans la collection ; ça donne
effectivement les durées de vie que tu as actuellement. Et ça
marche même s'il t'arrive des cycles dans la graphe.
En passant, est-ce que tu es sûr que tu veux un
std::set< CSimplex >, et non un std::set< CSimplex* > ?
Mettre un élément dans une collection impose des copies, et
la copie d'un objet avec deux multiset n'est pas forcément
bon marché. D'autant plus que si l'objet a des parents et
des enfants, il y a bien des chances que son identité soit
importante. En plus, si tu utilises des pointeurs partout,
tu pourrais changer plus tard pour un std::vector, ou que
sais-je, avec moins de problèmes.
C'est vrai qu'à bien y réfléchir, je vais sûrement utiliser
cette solution.
Alors, considère aussi l'utilisation du collecteur de Boehm ou
de boost::shared_ptr.
En général, je me méfie de l'utilisation des itérateurs
autrement que pour l'itération. Selon le type de la
collection, ils ont une validité plus ou moins délicate. La
même chose vaut pour les adresses des objets dans une
collection ; la collection est libre de les copier, et de
se servir de la copie, dans certains cas. Alors, la
navigation ne se fait pas entre des éléments d'une
collection ; s'il faut naviguer entre des objets, on met
des pointeurs à ces objets dans les collections, et non les
objets même.
Oui, les set garantissent des iterateur toujours valides, donc
j'avais pensé que ce serait plus "C++" d'utiliser des
itérateurs... Apparemment ce n'était pas une bonne idée ;o)
Les itérateurs sont là pour itérer. Leur nom en dit tout. La
force du C++, c'est d'être un langage multi-paradigme. La façon
la plus "C++", c'est d'utiliser le paradigme qui convient le
mieux à ce qu'on veut faire (plutôt qu'un imposé par le
langage).
--
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
-- Sinon, tu utilises les pointeurs à des CSimplex, plutôt que des itérateurs. std::set garantit que les pointeurs à un élément soient valides aussi longtemps que l'élément est dans la collection.
Oui j'y avais pensé mais ça m'oblige à faire des new et des delete...
C'est vrai. Mais de l'autre part, tu navigues entre les objets. Ça suppose que les objets ont une identité -- que tu ne peux pas librement remplacer un objet par une copie. Or, si c'est vrai qu'on peut s'en tirer avec std::set<CSimplex>, en faisait bien attention, c'est à mon avis fragile, parce qu'il va à l'encontre de la philosophie générale de la STL : qu'on met des valeurs, qui peuvent être librement copiées, dans les collections, et non des entités. Vue la sémantique apparente de tes objets, j'interdirais même la copie et l'affectation, et alors, évidemment, impossible à les mettre dans une collection quelconque.
A priori, j'ai l'impression que tes objets représentent une graphe. Il se peut qu'il y a des parties que tu n'as pas montré, parce qu'elles n'avaient pas d'importance pour la question, mais si leurs destructeurs ne font que de libéré la mémoire, la solution idéale serait de se servir simplement du collecteur de Boehm ; il faudra toujours des new, pour créer les objets, mais une fois que tu n'y peux plus accéder, ils disparaissent tout seuls ; pas besoin d'un delete. (Pour profiter pleinement du ramasse-miettes, il faudrait modifier la STL un peu. Mais les classes en question, c'est std::vector et std::deque ; il n'y a pas de problème avec des collections basées sur des vertices, genre std::list ou std::set.)
Sinon, et si tu veux que la collection soit le propriétaire final des objets, que leur durée de vie correspond bien à celle de la collection, et que ce soit elle qui les détruit, il existe la solution d'une collection des pointeurs intelligents, des boost::shared_ptr, par exemple. Dans ce cas si, je me démande même si la solution n'est pas d'utiliser les pointeurs bruts à peu près partout sauf dans la collection ; ça donne effectivement les durées de vie que tu as actuellement. Et ça marche même s'il t'arrive des cycles dans la graphe.
En passant, est-ce que tu es sûr que tu veux un std::set< CSimplex >, et non un std::set< CSimplex* > ? Mettre un élément dans une collection impose des copies, et la copie d'un objet avec deux multiset n'est pas forcément bon marché. D'autant plus que si l'objet a des parents et des enfants, il y a bien des chances que son identité soit importante. En plus, si tu utilises des pointeurs partout, tu pourrais changer plus tard pour un std::vector, ou que sais-je, avec moins de problèmes.
C'est vrai qu'à bien y réfléchir, je vais sûrement utiliser cette solution.
Alors, considère aussi l'utilisation du collecteur de Boehm ou de boost::shared_ptr.
En général, je me méfie de l'utilisation des itérateurs autrement que pour l'itération. Selon le type de la collection, ils ont une validité plus ou moins délicate. La même chose vaut pour les adresses des objets dans une collection ; la collection est libre de les copier, et de se servir de la copie, dans certains cas. Alors, la navigation ne se fait pas entre des éléments d'une collection ; s'il faut naviguer entre des objets, on met des pointeurs à ces objets dans les collections, et non les objets même.
Oui, les set garantissent des iterateur toujours valides, donc j'avais pensé que ce serait plus "C++" d'utiliser des itérateurs... Apparemment ce n'était pas une bonne idée ;o)
Les itérateurs sont là pour itérer. Leur nom en dit tout. La force du C++, c'est d'être un langage multi-paradigme. La façon la plus "C++", c'est d'utiliser le paradigme qui convient le mieux à ce qu'on veut faire (plutôt qu'un imposé par le langage).
-- 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
Clément
Bonjour,
Désolé pour le retard de ma réponse, j'ai été un peu occupé ces derniers jours... J'utilise désormais des pointeurs et j'en suis très heureux ;o) Merci pour les suggestions de Garbage Collector, mais j'utilise plus simplement le destructeur de la classe contenant mes ensembles pour désallouer la mémoire. A moins qu'il y ait une objection à cela ?
Merci encore, James, pour les réponses très complètes et constructives. Clément
Bonjour,
Désolé pour le retard de ma réponse, j'ai été un peu occupé ces derniers
jours...
J'utilise désormais des pointeurs et j'en suis très heureux ;o)
Merci pour les suggestions de Garbage Collector, mais j'utilise plus
simplement le destructeur de la classe contenant mes ensembles pour
désallouer la mémoire. A moins qu'il y ait une objection à cela ?
Merci encore, James, pour les réponses très complètes et constructives.
Clément
Désolé pour le retard de ma réponse, j'ai été un peu occupé ces derniers jours... J'utilise désormais des pointeurs et j'en suis très heureux ;o) Merci pour les suggestions de Garbage Collector, mais j'utilise plus simplement le destructeur de la classe contenant mes ensembles pour désallouer la mémoire. A moins qu'il y ait une objection à cela ?
Merci encore, James, pour les réponses très complètes et constructives. Clément