OVH Cloud OVH Cloud

Sort STL

27 réponses
Avatar
horneta2005
j essaye de mettre en ouvre une fonction de comparaison pour
std::sort mais d apres les exemple que j ai vu je ne comprend pas
leur fonctionnement notament le role de opeator()

7 réponses

1 2 3
Avatar
David Deharbe
Je propose la solution suivante:

Créer une classe (ou un patron de classe) isLessThan avec deux
méthodes:

isLessThan::SetThreshold(const MyType &);
bool isLessThan::Test(const MyType &);

Le tri peut alors être réalisé de la forme suivante:

isLessThan f;

f.SetThreshold(myValue);
std::sort( v.begin(), v.end(), isLessThan.Test )

Voilà - reste à vérifier comment coder cela proprement, mais l'idée
doit y être...

David.
--
Avatar
Fabien LE LEZ
On Thu, 06 Oct 2005 04:03:55 +0200, Fabien LE LEZ
:

Mauvais contre-exemple AMHA :


Désolé, je me suis emmêlé les pinceaux.

Avatar
kanze
Stan wrote:
"kanze" a écrit dans le message de news:


Il y a encore un problème avec son exemple : for_each (comme


Satanné exemple !

tous les algorithmes) prend l'objet fonctionnel par valeur,
c-à-d qu'il en reçoit une copie, et non l'objet initial. Ce
qui veut dire que sum ne serait pas modifié dans l'exemple
ci-dessus.


Ca ne t'arrive jamais d'oublier un truc dans un post ? Ah
non, quand c'est moi, c'est une erreur, et quand c'est toi,
c'est un oubli ou une faute de frappe.


Ce n'était pas une critique. Ou plutôt, c'était une critique de
la STL. AMHA, ce que tu as écrit est natural, et *doit*
marcher. Si j'ai soulevé le point, c'était bien pour montrer des
problèmes avec la STL.

TSum sum(0);
sum = for_each( v.begin( ), v.end( ), sum );
std::cout << "total= " << sum.res( ) << std::endl;


Qui n'est toujours pas garanti, selon la norme. Je crois que
l'intention était que ça marche, mais comme j'ai montré dans un
autre posting, il n'y a absolument rien dans la norme qui le
garantit.

Et évidemment, le problème est plus général. for_each n'est
qu'un exemple. Comme dit Fabien, elle donne une garantie
supplémentaire, mais... ce n'est pas la seule fonction où le
problème pourrait se présenter. En fin de compte, la STL est
assez mal spécifiée, et plein de petites pièges.

Faut-il que je développe le code de TSum pour s'assurer
qu'elle fonctionne bien ?


Ça ne servira à rien. Parce qu'elle fonctionnera, mais « par
hazard », dans le sens que la norme ne donne pas les garanties
requises, même si ça marche en fait avec toutes les
implémentations que je connais.

Et je repète, le problème n'est pas chez toi, ni dans ton code.
Le problème, c'est dans la norme.

--
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
David Deharbe wrote:
Je propose la solution suivante:

Créer une classe (ou un patron de classe) isLessThan avec deux
méthodes:

isLessThan::SetThreshold(const MyType &);
bool isLessThan::Test(const MyType &);

Le tri peut alors être réalisé de la forme suivante:

isLessThan f;

f.SetThreshold(myValue);
std::sort( v.begin(), v.end(), isLessThan.Test )


C'est quoi, ce dernier paramètre ?

Voilà - reste à vérifier comment coder cela proprement, mais
l'idée doit y être...


Je n'arrive pas réelement à saisir l'idée. Qu'est-ce que tu
essaies de passer comme troisième paramètre ? isLessThan n'est
pas un objet ; on ne peut donc pas y appliquer l'opérateur `.'.
isLessThan::Test est une fonction membre, qu'on ne peut pas
passer comme paramètre non plus ; on peut en prendre l'adresse
(&isLessThan::Test), mais alors, qu'est-ce que std::sort va en
faire ? On ne peut se servir d'un pointeur à membre qu'avec un
objet (ou un pointeur à un objet) du bon type, et std::sort n'en
a pas. Et si c'est f.Test que tu voulais dire, c'est une
expression qui a un type un peu particulier, qui ne peut pas
servir comme paramètre à un template. (Voir §5.2.5/4, deuxième
sous-point du troisième point : « [...] The expression
designates a non-static member function. The expression can be
used ONLY as the left-hand operand of a member function call. »)

--
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
Stan
"kanze" a écrit dans le message de news:

Et évidemment, le problème est plus général. for_each n'est
qu'un exemple. Comme dit Fabien, elle donne une garantie
supplémentaire, mais... ce n'est pas la seule fonction où le
problème pourrait se présenter. En fin de compte, la STL est
assez mal spécifiée, et plein de petites pièges.


Je suppose qu'on retrouve ce genres
de problèmes dans autres bibliothèques ?

--
-Stan

Avatar
David Deharbe
Oui, c'est f.test que je voulais utiliser. Merci pour la correction.

Ma première idée, c'est effectivement de passer un objet fonction en
paramêtre.

En lisant "Effective C++", item 35, j'ai découvert tr1::function qui
doit permettre d'être encore plus "élégant" en permettant une sorte
de curryfication au moyen de bind. La deuxième idée est alors de
revisiter sort pour que le troisième paramêtre soit du type:
std::tr1::function<bool (const MyType &)>

L'appel deviendrait alors (peut-être):
sort(v.begin(), v.end(), std:;tr1::bind(greater<MyType &>, threshold,
_1));

David.
--
Avatar
kanze
David Deharbe wrote:
Oui, c'est f.test que je voulais utiliser. Merci pour la correction.

Ma première idée, c'est effectivement de passer un objet
fonction en paramêtre.

En lisant "Effective C++", item 35, j'ai découvert
tr1::function qui doit permettre d'être encore plus "élégant"
en permettant une sorte de curryfication au moyen de bind. La
deuxième idée est alors de revisiter sort pour que le
troisième paramêtre soit du type: std::tr1::function<bool
(const MyType &)>

L'appel deviendrait alors (peut-être):
sort(v.begin(), v.end(), std:;tr1::bind(greater<MyType &>,
threshold, _1));


Quelque chose de ce genre. (Avec probablement boost:: à la place
de std::tr1 pour l'instant.) Dans ce cas précis, je crois qu'on
pourrait y arriver uniquement avec les objets fonctionnels de la
norme, quelque chose du genre : « std::bind2nd(
greater<MyType>(), threshold ) ». Sinon, avec boost::lambda, je
crois qu'on peut écrire quelque chose comme :

std::sort( v.begin(), v.end(), _1 > threashold ) ;

(Ceci dit : je vois mal comment ce genre de fonction puisse
servir pour std::sort:-). std::find_if, peut-être ?)

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

1 2 3