Et bon, je trouve plus propre d'avoir un swap dans ton namespace et laissez l'ADL le trouver plutot que de hacker std. mais comme dis plus, préférences personelles.
Version imprimable
Et bon, je trouve plus propre d'avoir un swap dans ton namespace et laissez l'ADL le trouver plutot que de hacker std. mais comme dis plus, préférences personelles.
On peut pas spécialiser partiellement une fonction template...
Sinon +1 pour l'ADL. J'aime pas ouvrir le namespace std dans mes fichiers... C'est psychologique sûrement.
argument dependent name lookup
C'est ce qui te permet d'écrire :
std::cout << "foo";
sans soucis. (ie t'éviter std::cout std::operator<<("foo"); )
lol, on aprend des choses tous les jours :D
Par contre, comment tu définie le swap dans ton namespace pour que l'ADL trouve la bonne implémentation pour la STL?
J'ai beau essayer, j'y arrive pas (sous visual 2008)
dans ce code, seule la spécialisation de la std est appelé lors du sort.Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75 #include <algorithm> #include <iostream> #include <vector> #include <string> namespace AA { class A { public : A(int a) :nb(a) { }; bool operator<(const A& a) { return nb<a.nb; } A& operator=(const A& a) { nb = a.nb; return (*this); } void swap(A& a) { std::swap(nb,a.nb); }; private: int nb; }; template<typename T> void swap ( T& a, T& b ) { std::cout<<"AA::std::swap"<<std::endl; std::swap(a,b); }; //specialisation de la fonction swap pour la class A template<> void swap<A> ( A& a, A& b ) { std::cout<<"AA::swap"<<std::endl; a.swap(b); }; }//fin namespace template<> void std::swap<AA::A> ( AA::A& a, AA::A& b ) { std::cout<<"std::swap"<<std::endl; a.swap(b); }; int main(int argc, char** argv) { //mon vecteur a trier std::vector<AA::A> vect; //on remplie de n'importe quoi for(int i =0 ; i < 1000 ; ++i) vect.push_back(AA::A(rand())); //on fait le trie std::sort(vect.begin(),vect.end()); AA::A a(10); AA::A b(20); swap(a,b); return 0; }
Seule swap(a,b) utilise le swap définie dans le namespace.
si je fait (dans le code précédent et un S majuscule dans la fonction de la classe)
visual me faitCode:
1
2
3
4
5 swap ( A& a, A& b ) { // std::cout<<"AA::swap"<<std::endl; a.Swap(b); };
et si je faitCitation:
spécificateur de type manquant - int est pris en compte par défaut.
la fonction n'est appelé que par swap(a,b) et jamais par le sort.Code:
1
2
3
4
5 void swap ( A& a, A& b ) { // std::cout<<"AA::swap"<<std::endl; a.Swap(b); };
Je doit bien m'être planté quelque part mais je ne voie pas ou...
Et si tu mets ceci dans AA::A:
Puis dans AA:Code:
1
2 private: friend bool operator<(A const& a, A const& b);
Edit: finalement, j'ai testé (avec gcc). Ca fonctionne:Code:
1
2
3
4 bool operator<(A const& a, A const& b) { return a.nb<b.nb; }
(désolé, l'indentation doit être merdique)Code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75 #include <algorithm> #include <iostream> #include <vector> #include <string> #include <iterator> namespace AA { class A { public: A(int a) :nb(a) { }; bool operator<(const A& a) { return nb<a.nb; } A& operator=(const A& a) { nb = a.nb; return (*this); } void swap(A& a) { std::swap(nb,a.nb); }; private: int nb; friend bool operator<(const A& a, const A& b); friend std::ostream& operator<<(std::ostream& o, A const& a); }; void swap ( A& a, A& b ) { std::cout<<"AA::swap"<<std::endl; a.swap(b); }; bool operator<(const A& a, const A& b) { return a.nb<b.nb; } std::ostream& operator<<(std::ostream& o, AA::A const& a) { return o << a.nb; } }//fin namespace int main(int argc, char** argv) { //mon vecteur a trier std::vector<AA::A> vect; //on remplie de n'importe quoi for(int i =0 ; i < 1000 ; ++i) vect.push_back(AA::A(rand())); //on fait le trie std::sort(vect.begin(),vect.end()); std::copy(vect.begin(), vect.end(), std::ostream_iterator<AA::A>(std::cout, ",")); AA::A a(10); AA::A b(20); swap(a,b); return 0; }
je voie pas trop ce que cela changerai... mais ça na rien changé.
Par contre sous gcc ça marche.
Si je regarde le code de sort, visual utilise std::swap alors que gcc utilse swap. C'est dans la définition de iter_swap
Donc ca expliquerai mon problème.
[edit]
Si je remplace std::swap par swap dans le fichier algorithm de visual, ça marche... Mais bon, je suis pas sur que c'est une solution...
Par défaut, c'est une très très très mauvaise idée que de vouloir aller modifier un fichier d'en-tête standard (ou de toute bibliothèque dont tu ne dispose pas explicitement le code source d'ailleurs :P)
Il ne faut pas oublier que, malgré que la bibliothèque standard soit en grande partie basée sur des template, il est possible d'avoir des dlls ou des en-têtes pré compilées de celle-ci (quand on compile gcc avec l'option --enable-shared, on obtient une dll stdc++ et une autre supc++), même si on se doute parfaitement que les parties implémentées par celles-ci ne peuvent forcément pas être prévues pour fonctionner avec n'importe quel type (sans doutes les types primitifs, les std::string et les différent I/Ostream ?)
Si tu modifie le fichier d'en-tête standard sans faire attention, va savoir quelles régressions tu risques d'occasionner en espérant résoudre un problème pouvant être considéré comme marginal :P
Je me doutais que, venant de toi, il n'y avait pas énormément de risques que tu laisse le fichier d'en-tête ainsi modifié, mais je voulais surtout attirer l'attention de toute personne lisant cette discussion sur le fait que c'était une très mauvaise idée (des fois qu'il y ait un quidam quelconque qui puisse croire que c'était la solution à son problème :P)
Pour peu (je n'ai pas été vérifier) que la norme n'ait pas été très précise sur la manière de s'y prendre, ou qu'elle ait précisé que c'était défini par l'implémentation, ce n'est pas *forcément* surprenant...Citation:
Je suis étonné que visual et gcc ont un comportement différent sur ce point...
Il faut aussi voir les "casseroles" tirées par l'historique des différents compilateurs sur le sujet...
Je rappelle quand même que, jusqu'à il n'y a que quelques années, microsoft était connu pour ne respecter les normes que de la manière qu'il voulait bien ;) (non, je n'essaye pas de relancer un troll... toute allusion à cette dernière phrase sera supprimée "a vue" :D)
Je viens de tester au travaille. Sous visual 2008 sp1 ça marche en faite.
La fonction iter_swap utilise bien swap.
Chez moi j'utilise visual 2008 express et c'est avec lui que ça ne marche pas :koi:
Il me semblais que la version express correspondait à visual 2008 sp1 pour la compilation.
J'ai pas le temps de chercher quel est l'etat actuel, d'autant plus que l'abandon des concepts a du avoir un effet important. Voir http://www.open-std.org/jtc1/sc22/wg...2001/n1296.asc pour C++98