Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

[VC2005, STL] "could not deduce template argument"

8 réponses
Avatar
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;

class CSimplex
{
public:
/// Constructeur
CSimplex(DWORD dimension, point3Iterator iteratorToPoint3);
/// Destructeur
virtual ~CSimplex();
//------------------------------------------------- Méthodes publiques
bool operator<(const CSimplex &s2) const;
protected :
//------------------------------------------------- Attributs protégés
DWORD m_dimension;
point3Iterator m_iteratorToPoint3;
std::multiset<simplexIterator> m_children;
std::multiset<simplexIterator> m_parents;
};

inline bool operator<(const simplexIterator &s1, const simplexIterator &s2)
{
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 :

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

Clément.

8 réponses

Avatar
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 :

class simplexIteratorCmp
{
public:
bool operator()(const simplexIterator & s1, const simplexIterator & s2)
const;
};

avec

bool simplexIteratorCmp::operator()(const simplexIterator &s1, const
simplexIterator &s2) const
{
return (*s1 < *s2);
}

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+

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

class CSimplex
{
public:
/// Constructeur
CSimplex(DWORD dimension, point3Iterator iteratorToPoint3);
/// Destructeur
virtual ~CSimplex();
//------------------------------------------------- Méthodes publiques
bool operator<(const CSimplex &s2) const;
protected :
//------------------------------------------------- Attributs protégés
DWORD m_dimension;
point3Iterator m_iteratorToPoint3;
std::multiset<simplexIterator> m_children;
std::multiset<simplexIterator> m_parents;
};

inline bool operator<(const simplexIterator &s1, const simplexIterator &s 2)


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

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

Avatar
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;
};

avec

bool simplexIteratorCmp::operator()(const simplexIterator &s1, const
simplexIterator &s2) const
{
return (*s1 < *s2);
}

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


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

Avatar
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


Avatar
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