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

spécification de la fonction de comparaison des conteneurs de la STL...

5 réponses
Avatar
Frédéric Gourul
Bonsoir,

Une question bien précise sur laquelle je bloque. Je souhaite stocker des
pointeurs de ma classe dans un conteneur (std::set). Seulement je voudrais
que la fonction d'ordre du conteneur soit celle de ma classe et non les
adresses de pointeurs comme c'est le cas actuellement.

class CTest
{
private:
int priority;
public:
CTest(int priority) :priority(priority) {}
int getPriority() const {return priority;}
};
ostream& operator<<(ostream& s, const CTest m) {s << "CTest - " <<
m.getPriority(); return s;}
bool operator<(const CTest m1, const CTest m2) {return (m1.getPriority() <
m2.getPriority());}
bool operator>(const CTest m1, const CTest m2) {return (m1.getPriority() >
m2.getPriority());}
bool operator==(const CTest m1, const CTest m2) {return (m1.getPriority() ==
m2.getPriority());}
bool operator<=(const CTest m1, const CTest m2) {return (m1.getPriority() <=
m2.getPriority());}
bool operator>=(const CTest m1, const CTest m2) {return (m1.getPriority() >=
m2.getPriority());}

si je fais:
....
CTest t1(8), t2(5), t3(13), t4(9);
std::set<CTest*> queue;
queue.insert(&t1);
queue.insert(&t2);
queue.insert(&t3);
queue.insert(&t4);
std::set<CTest*>::iterator it = queue.begin();
while(it != queue.end()) cout << **it++ << "; ";
cout << endl;

j'obtiens ceci comme résultat, ce qui est normal...
CTest - 9; CTest - 13; CTest - 5; CTest - 8;

or moi je veux:
CTest - 5; CTest - 8; CTest - 9; CTest - 13;

je sais que je doit spécifier la fonction de comparaison en deuxième
paramètre du template, mais j'ignore comme faire cela... Je n'arrive même
pas à le faire avec une fonction globale...

merci de votre aide :)

5 réponses

Avatar
Fabien LE LEZ
On Mon, 12 Jan 2004 23:37:21 +0100, "Frédéric Gourul"
wrote:

class CTest
{
private:
int priority;
public:
CTest(int priority) :priority(priority) {}
int getPriority() const {return priority;}
};


bool CompareCTest (CTest* const& c1, CTest* const& c2)
{
return c1->getPriority() < c2->getPriority();
}

std::set <CTest*, CompareCTest> mon_set;

Au fait, le préfixe "C" est typique des classes de la MFC, il ne me
paraît pas utile (ni même bon) de l'utiliser pour tes propres classes.


--
;-)

http://www.gotw.ca/gotw/063.htm
http://www.gotw.ca/gotw/067.htm#2

Avatar
Fabien LE LEZ
On Tue, 13 Jan 2004 01:03:54 +0100, Fabien LE LEZ
wrote:
bool CompareCTest (CTest* const& c1, CTest* const& c2)
{
return c1->getPriority() < c2->getPriority();
}

std::set <CTest*, CompareCTest> mon_set;


Ahem... On va dire que je ferais mieux d'aller me coucher :-(

La vraie syntaxe est bien sûr :

struct CompareCTest
{
bool operator()(CTest* const& c1, CTest* const& c2) const
{
return c1->getPriority() < c2->getPriority();
}
};

std::set <CTest*, CompareCTest> mon_set;

Celle que j'ai donnée précédemment ne fonctionne que comme paramètre
de fonction (std::sort par exemple).

--
;-)

http://www.gotw.ca/gotw/063.htm
http://www.gotw.ca/gotw/067.htm#2

Avatar
Frédéric Gourul
"Fabien LE LEZ" a écrit dans le message de
news:
On Tue, 13 Jan 2004 01:03:54 +0100, Fabien LE LEZ
wrote:

Au fait, le préfixe "C" est typique des classes de la MFC, il ne me
paraît pas utile (ni même bon) de l'utiliser pour tes propres classes.


Exact. Aucune de mes classes n'utilise cette convention. Le "C" ici veut
juste dire "Classe Test"...

std::set <CTest*, CompareCTest> mon_set;

Celle que j'ai donnée précédemment ne fonctionne que comme paramètre
de fonction (std::sort par exemple).


Merci. Effectivemment j'avais essayé "naturellement" la fonction que tu as
donné précédemment et j'ai bien vu que ce n'était pas ca... J'avoue que j'ai
un peu de mal avec les foncteurs... Une dernière question: il n'est pas
possible de lui spécifier l'opérateur de comparaison de ma classe ? Même si
je la déclare comme fonction membre: CTest::operator<(const CTest&) ?

Avatar
Fabien LE LEZ
On Tue, 13 Jan 2004 08:00:25 +0100, "Frédéric Gourul"
wrote:

Une dernière question: il n'est pas
possible de lui spécifier l'opérateur de comparaison de ma classe ?


Non. std::set est défini à peu près comme suit :
template <class T, class Compare = std::less<T> > class set {...
Aussi, le deuxième paramètre du template doit impérativement être une
classe. Note : il pourrait plus généralement être un type, mais aucun
type de base ne convient ici.

A comparer avec :

template <class Iterateur, class Foncteur>
void sort (Iterateur debut, Iterateur fin, Foncteur f);

Tu peux passer une fonction comme paramètre, car ici le paramètre "f"
est un objet, pas un type (le type "Foncteur" est alors le type
"pointeur sur fonction").

La différence, c'est pour pour créer un objet d'une classe template,
tu dois préciser explicitement les paramètres templates, alors que
pour une fonction, ce n'est généralement pas nécessaire (Heureusement,
car souvent les pointeurs de fonctions sont pas piqués des hannetons
;-) ).

--
;-)

http://www.gotw.ca/gotw/063.htm
http://www.gotw.ca/gotw/067.htm#2

Avatar
Michel Michaud
Dans news:, Fabien LE
Non. std::set est défini à peu près comme suit :
template <class T, class Compare = std::less<T> > class set {...
Aussi, le deuxième paramètre du template doit impérativement être
une classe. Note : il pourrait plus généralement être un type, mais
aucun type de base ne convient ici.

A comparer avec :

template <class Iterateur, class Foncteur>
void sort (Iterateur debut, Iterateur fin, Foncteur f);

Tu peux passer une fonction comme paramètre, car ici le paramètre
"f" est un objet, pas un type (le type "Foncteur" est alors le type
"pointeur sur fonction").


Mais les constructeurs de set permettent de donner une fonction
de comparaison... d'une certaine façon ! (ce n'est pas vraiment
plus simple...)

--
Michel Michaud
http://www.gdzid.com
FAQ de fr.comp.lang.c++ :
http://www.cmla.ens-cachan.fr/~dosreis/C++/FAQ/