[C++] qsort() sur des templates

qsort() sur des templates [C++] - C++ - Programmation

Marsh Posté le 06-10-2005 à 23:05:09    

Bonsoir,
 
Dans ma classe Map, j'ai une méthode de tri (pour trier un tableau de taille fixe connue) dont voici le code :

Code :
  1. template <typename Enreg>
  2. void Map<Enreg>::_tri(void) {
  3. // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclib/html/_crt_qsort.asp
  4. qsort(
  5.  (void *)this->Liste, // Le tableau contenant des MapModule<Enreg>
  6.  this->nb_enreg, // Le nombre de cellules du tableau
  7.  this->sizeof_MapModule, // La taille d'un MapModule<Enreg> (obtenue avec sizeof())
  8.  Map_comparaison_croissant<Enreg> // Ma fonction de tri
  9. );
  10. }


Et la fonction de tri est :

Code :
  1. template <typename Enreg>
  2. int Map_comparaison_croissant(const void *element1, const void *element2) {
  3. return strcmp((*(MapModule<Enreg>*)element1).get_cle(), (*(MapModule<Enreg>*)element2).get_cle());
  4. }


Et là où j'ai un problème c'est que Visual C++ 6.0 me dit :

Citation :

classes-map.h(192) : error C2664: 'qsort' : cannot convert parameter 4 from 'int (const void *,const void *)' to 'int (__cdecl *)(const void *,const void *)'


J'ai bien essayé de mettre, à tout hasard, (__cdecl *) (un cast) devant le 4ème argument de qsort ("Map_comparaison_croissant<Enreg>" ), mais il me sort un : syntax error : '__cdecl'.
 
J'ai fait des tests et j'arrive à faire fonctionner un qsort tant que la fonction de comparaison n'est pas sur un type générique.
Est-ce peine perdue ?

Reply

Marsh Posté le 06-10-2005 à 23:05:09   

Reply

Marsh Posté le 06-10-2005 à 23:59:17    

pas de sqort. utilise std::sort

Reply

Marsh Posté le 07-10-2005 à 00:02:46    

Je comprends pas ?
Je ne peux pas employer le tri rapide dans ce cas là ?
 
Qu'est-ce que std::sort ? (je ne suis pas encore très très familier avec toutes les librairies C/C++).

Reply

Marsh Posté le 07-10-2005 à 00:27:52    

std::sort c'est le tri C++. qsort c'est du C avec tous ses défauts.

Reply

Marsh Posté le 07-10-2005 à 23:23:46    

et de toute façon pour obtenir l'adresse d'une méthode le & devant est obligatoire. Il est optionnel pour les fonctions globales "à la C".
 
Mais Taz a raison, en C++ il faut utiliser std::sort qui marche avec des itérateurs. Sachant qu'un pointeur est un itérateur, c'est pas trop contraignant. Les algos présents dans le C++ sont bien + nombreux que ceux du C. D'ailleurs en C, à part qsort...
 
exemple :

Code :
  1. int tab[] = {2, 42, -6, 45 };
  2. std::sort(tab, tab + 4);


 
le tri se fait avec l'operator< par défaut.
 
edit : ta fonction de comparaison semble bien être un fonction et pas une méthode. Dans ce cas :

Code :
  1. // edit : après remarque de Taz, ce code n'est pas bon car cette fonction est templatée. Sans template ça marcherait
  2. extern "C"
  3. {
  4.    template <typename Enreg>
  5.    int Map_comparaison_croissant(const void *element1, const void *element2) {
  6.        return strcmp((*(MapModule<Enreg>*)element1).get_cle(), (*(MapModule<Enreg>*)element2).get_cle());
  7.    }
  8. }
  9. template <typename Enreg>
  10. void Map<Enreg>::_tri(void) {
  11.     // http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vclib/html/_crt_qsort.asp  
  12.     qsort(
  13.         (void *)this->Liste, // Le tableau contenant des MapModule<Enreg>  
  14.         this->nb_enreg, // Le nombre de cellules du tableau  
  15.         this->sizeof_MapModule, // La taille d'un MapModule<Enreg> (obtenue avec sizeof())  
  16.         &(Map_comparaison_croissant<Enreg> ) // Ma fonction de tri  
  17.     );
  18. }


devrait marcher à vu de nez. mais ça reste mauvais.

Message cité 1 fois
Message édité par jesus_christ le 13-10-2005 à 21:41:11
Reply

Marsh Posté le 08-10-2005 à 09:58:18    

jesus_christ a écrit :


Mais Taz a raison, en C++ il faut utiliser std::sort qui marche avec des itérateurs. Sachant qu'un pointeur est un itérateur, c'est pas trop contraignant. Les algos présents dans le C++ sont bien + nombreux que ceux du C. D'ailleurs en C, à part qsort...


 
Sans vouloir sodomiser des dyptéres, il me semble qu'il y a quand même une *légére* différence masi si leur sémantique est identique  :D

Reply

Marsh Posté le 08-10-2005 à 11:08:22    

il sert à quoi ton extern C ?

Reply

Marsh Posté le 08-10-2005 à 20:35:01    

En effet, "Map_comparaison_croissant()" n'est pas une méthode de classe mais bien une fonction.
 
jesus_christ, pour ton exemple, j'obtiens "'std' : is not a class or namespace name", quelle librairie dois-je inclure avant d'utiliser std::sort ?

Reply

Marsh Posté le 08-10-2005 à 20:46:53    

la bibliothèque <algorithm>
 
lis la doc bon sang !

Reply

Marsh Posté le 10-10-2005 à 21:23:10    

Taz a écrit :

il sert à quoi ton extern C ?


à ce que le type du pointeur de fonction soit bien (__cdecl*) sous visual c++
 
Joel F : c'est pas seulement sémantique, les pointeurs sont un cas particulier des itérateurs.
Souvent (avant) vector<T>::iterator était défini comme T*, même si ça ne ce fait plus trop et que ça peut inciter à faire du code pas portable.
Bien sur à part sur les tableaux et les vecteurs* (et dans le sens normal, pas reverse) les pointeurs ne vont pas très loin.
 
* : si les vecteurs stockent de façon contigue, ce qui doit normalement être le cas.

Reply

Marsh Posté le 10-10-2005 à 21:23:10   

Reply

Marsh Posté le 10-10-2005 à 23:33:12    

j'y comprends rien à votre compilo de merde.

Reply

Marsh Posté le 11-10-2005 à 00:16:43    

visual c++ n'est peut-être pas le compilo le + conforme à l'ISO98 mais c'est un des meilleurs sous win et il a de très loin le meilleur debugger.
Sans compter que VC6 a été écrit en 97 et a donc une bonne excuse pour pas être conforme, quant à VC7 et VC8 il sont très proches du standard. Microsoft a isolé toutes ses "exotismes" dans .net/C# et a laissé le C++ "pur".
 
VC type les fonctions selon leur convention d'appel. __cdecl pour le C, __thiscall pour les méthodes C++, __stdcall pour les appels standard win(utile pour linker avec du VB par exemple, diff sur callee-save et caller-save) et __fastcall pour passer les paramètres par les registres.

Reply

Marsh Posté le 11-10-2005 à 02:38:57    

je m'en fout. extern "C" autour d'un truc C++ c'est un non-sens.

Reply

Marsh Posté le 11-10-2005 à 21:15:57    

c'est pourtant cité dans le Stroustrup. extern défini un linkage et pas un langage -> chap (9.2) En plus son explemple c'est justement le qsort avec une fonction extern "C"

Reply

Marsh Posté le 11-10-2005 à 21:29:02    

justement ... tu ferais mieux de le lire le stroustrup. Du code C++ ne peut avoir un linkage C.

Reply

Marsh Posté le 11-10-2005 à 22:55:15    

j'ai vérifié et il dit bien que toutes les combinaisons sont possible. Et puis du code C++ c'est vite fait, genre

Code :
  1. int f(void)
  2. {
  3.   int a;
  4.   a = 3;
  5.   int b;
  6. }


c'est du C++ et pas du C89, pourtant le linkage extern "C" marche. En cas de template ou de pointeur de méthode, enfin des trucs "très C++" peut-être qu'il n'existe pas de linkage C. Du code C++ peut dans certains cas ne pas être linké en C, mais c'est la plupart du temps possible.
Trouve moi un compilo ou une ligne du Stroustrup qui interdit ça :

Code :
  1. class Bidule
  2. {
  3. public :
  4.    void toto(void) { cout << "toto\\n"; }
  5. };
  6. extern "C" void C_toto(void)
  7. {
  8.    Bidule b;
  9.    b.toto();
  10. }


et on en reparle.


Message édité par jesus_christ le 11-10-2005 à 22:56:23
Reply

Marsh Posté le 11-10-2005 à 23:00:24    

t'as toujours pas lu le stroustrup ça fait plaisir. t'as toujours pas compris à quoi ça servait. laisse tomber.

Reply

Marsh Posté le 11-10-2005 à 23:04:27    

je l'ai sur les genou, le stroustrup 3e edition. Dis moi où il définit les interdictions dont tu parles au lieu de décréter que j'ai pas compris. C'est peut-être vrai, mais argumente.
En attendant l'intro du chapitre 9.2.4 dit bien que la directive extern "truc" sert aussi bien à exporter qu'à importer des symboles de ou vers du C++.


Message édité par jesus_christ le 11-10-2005 à 23:11:04
Reply

Marsh Posté le 13-10-2005 à 14:52:40    

tu ne peux pas obtenir un symbol C++ avec un truc template, c'est ça que je veux dire ...

Reply

Marsh Posté le 13-10-2005 à 19:22:39    

Taz a écrit :

tu ne peux pas obtenir un symbol C++ avec un truc template, c'est ça que je veux dire ...


Tu fais bien de préciser :)
 
D'ailleurs, j'ai quand même regardé dans la norme, je n'ai trouvé aucun qui paragraphe qui mentionne cette interdiction, même si elle parait logique ... Mais j'ai peut etre pas les yeux en face des trous.

Reply

Marsh Posté le 13-10-2005 à 19:41:37    

c'est pas une interdiction, c'est un non-sens. Tu  ne peux avoir dans un bloc extern "C" que des symboles C. qsort a un linkage C, mais pas besoin de linkage C pour son argument fonction de comparaison.

Reply

Marsh Posté le 13-10-2005 à 19:44:01    

Taz a écrit :

tu ne peux pas obtenir un symbol C++ avec un truc template, c'est ça que je veux dire ...


ah là je suis d'accord, donc mon code est effectivement erroné, on ne peut pas obtenir de symbole C à partir d'un template. Mais on peut à partir d'une fonction C++ passablement proche du C.
 
Fab++ : idem, j'ai lu et relu (le stroustrup, pas la norme), ça ne me semble pas être écrit explicitement. Dans le même genre le fait que les classes locales aux fonctions ne soient pas linkables (même en C++ pur), je l'ai trouvé dans le lexique du site de stroustrup mais pas dans son livre.

Reply

Marsh Posté le 13-10-2005 à 19:50:11    

Taz a écrit :

c'est pas une interdiction, c'est un non-sens. Tu  ne peux avoir dans un bloc extern "C" que des symboles C. qsort a un linkage C, mais pas besoin de linkage C pour son argument fonction de comparaison.

Un symbole C++ ayant un sens en C (ni class ni objet ni template ni pointeur de méthode ni operator...) peut avoir un symbole C, c'est d'ailleur surtout à ça que ça sert.
 
si t'écris void f() {} dans un fichier compilé en tant que C++ c'est du C++ même si ça pourrait exister en C.

Reply

Marsh Posté le 13-10-2005 à 21:11:22    

Taz a écrit :

c'est pas une interdiction, c'est un non-sens. Tu  ne peux avoir dans un bloc extern "C" que des symboles C. qsort a un linkage C, mais pas besoin de linkage C pour son argument fonction de comparaison.


 
Oui, je voie mal un code C inclure un header dans lequel figure : extern "C" template<class T> void(T);
D'ailleurs, ça parait logique que ce soit mentionné nul part finalement.
Par contre, histoire de couper un cheveux en 4, qsort n'a pas forcément un linkage C ...

Reply

Marsh Posté le 13-10-2005 à 21:22:58    

pourtant c'est le code qui a été proposé.

Reply

Marsh Posté le 13-10-2005 à 21:41:44    

j'ai mis ta remarque dans mon code qui est effectivement erroné. :D

Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed