IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C++ Discussion :

Conversions (suite)


Sujet :

C++

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Inscrit en
    Septembre 2004
    Messages
    187
    Détails du profil
    Informations forums :
    Inscription : Septembre 2004
    Messages : 187
    Par défaut Conversions (suite)
    :pingoin: Bonjour,
    Dans une précédente discution on m'a conseiller d'utiliser le couple de fonction remove_if+erase pour faire du nettoyage dans une liste d'objet.

    J'ai à peu pres pigé le fonctionnement de tout ça et j'en ai fait une illustration:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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
    //Test.cpp
    #include <iostream>
    #include <list>
    #include <algorithm>
     
    using namespace std;
     
    class Point
    {
    	int x,y;
    public:
    	int Getx(){return x;}
    	int Gety(){return y;}
    	Point(int a=0,int b=0):x(a),y(b){}
    	virtual ~Point(){}
    };
    bool Clean(Point& aPoint)
    {
    	cout <<endl<<"Appel de Clean";
    	int val;	    
    	val = aPoint.Getx()-aPoint.Gety();
    	cout <<endl<<" val: "<<val<<endl;
    		if(!val){cout <<endl<<" val=0, je renvoie true ";return true;}
    		else return false;
     
    }	
    void Read(Point aPoint){cout <<"("<< (aPoint.Getx()) << "," << aPoint.Gety()<< ")" <<" ";}
    int main()
    {
     Point Points[5]={Point(1,0),Point(2,1),Point(3,3),Point(4,4),Point(5,7)};
     list <Point> Li(Points,Points+5);
     for_each(Li.begin(),Li.end(),Read);//****Affiche la liste****
     cout <<endl;
     Li.erase(remove_if(Li.begin(),Li.end(),Clean),Li.end());
     cout <<endl<<"***";
     for_each(Li.begin(),Li.end(),Read);
     cout <<endl<<"***"<<endl;
     return 0;
    }
    Jusque là tout va bien...
    Mais quand je veux appliquer à mon programme j'obtient:
    Compiling...
    Logic.cpp
    C:\...\EchecEtMat\Logic.cpp(92) : error C2664: 'remove_if' : cannot convert parameter 3 from 'bool (class CPieces &)' to 'bool (__thiscall *)(class CPieces &)'
    None of the functions with this name in scope match the target type
    Error executing cl.exe.
    EchecEtMat.exe - 1 error(s), 0 warning(s)

    Je resitue le probleme:
    j'ai une fonction Clean Membre d'une classe CLogic:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    bool CLogic::Clean(CPieces& aMove)
    {
    	int FlagPlay=GetFlag(MainFlag,Play);//Obtient le Flag du tour de jeu.	
    	if((FlagPlay*m_Plateau[IL1->Getx()][IL1->Gety()])>0)
    		return true;
    	else return false;
    }
    Que j'utilise au sein d'une autre fonction de CLogic dans la déclaration:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Recipient.erase(remove_if(Recipient.begin(),Recipient.end(),Clean),Recipient.end());
    Que veut dire __thiscall *)?
    Quelles sont les differences significatives entre Test.cpp et mon application
    qui empèchent le bon déroulement?
    Y-at-il un moyen d'y remedier?

  2. #2
    Membre averti
    Inscrit en
    Juin 2004
    Messages
    20
    Détails du profil
    Informations forums :
    Inscription : Juin 2004
    Messages : 20
    Par défaut
    L'erreur que tu obtiens provient d'un mauvais appel à la la fonction remove_if.

    Dans le premier exemple (test.cpp), la fonction remove_if appelle la fonction Clean.

    Dans ton code, tu utilise la fonction remove_if en lui passant en paramètre une méthode d'une classe.

    Le plus simple, c'est que tu transforme ta méthode de classe en fonction.

    Cela corrigera ton problème de compilation.

  3. #3
    Membre confirmé
    Inscrit en
    Septembre 2004
    Messages
    187
    Détails du profil
    Informations forums :
    Inscription : Septembre 2004
    Messages : 187
    Par défaut
    :pingoin: Bonjour,
    Si j'ai bien compris, tu me préconises de déclarer Clean en dehors de toute classe?
    Je viens d'essayer mais les variables utilisées passent toutes hors de portée.
    Est-ce que tu peux preciser la difference entre methode et fonction?

  4. #4
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Par défaut
    thiscall est la convention d'appel pour les fonctions membres. Or comme toute fonction membre, Clean va avoir besoin d'une instance de la classe pour être appelée, ce que ne peux pas faire remove_if tout seul. Deux solutions : faire de Clean une fonction globale (ou mieux : un foncteur), ou utiliser std::mem_fun_ref qui transforme les fonctions membres en fonctions non membres.

    Pour ce qui est de la différence entre méthode et fonction, il ne vaut mieux pas trop preter de sens à ce genre de terminologie mais en général méthode signifie fonction membre, et fonction signifie fonction non-membre.

    EDIT : en fait std::mem_fun_ref aurait fonctionné si Clean avait été membre de CPiece, je n'avais pas vu qu'il y avait une autre classe dans le coup. Là pas le choix : fonction non-membre.

  5. #5
    Membre confirmé
    Inscrit en
    Septembre 2004
    Messages
    187
    Détails du profil
    Informations forums :
    Inscription : Septembre 2004
    Messages : 187
    Par défaut
    :pingoin: Bonsoir,
    J'ai finalement contourner le probleme en sélectionnant les objets utiles en amont.
    Ainsi, je n'ai plus besoin de supprimer d'objets dans la liste.
    Cependant j'aimerais étudier les éléments de réponses plus précisement.
    Auriez vous un peu plus de détail sur std::mem_fun_ref parce que dans mes bouquins nada et dans ma doc electronique c'est plustôt succinct.
    Et puis ...c'est quoi un foncteur?

  6. #6
    Rédacteur
    Avatar de Laurent Gomila
    Profil pro
    Développeur informatique
    Inscrit en
    Avril 2003
    Messages
    10 651
    Détails du profil
    Informations personnelles :
    Âge : 41
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Par défaut
    Pour la doc sur la STL, tu peux aller voir le site de dinkumware ou bien celui de SGI.

    En gros :

    - std::mem_fun_ref (et ses copains std::mem_fun, std::mem_fun1, ...) sont des foncteurs (cf. après ) servant à transformer une fonction membre + une instance de classe en un truc appelable globalement.

    Exemple : avec std::for_each. Tu vas lui passer une séquence d'objets + une fonction, il va appeler cette fonction avec comme paramètre chacun des éléments de la séquence. Donc de la forme Fonction(Element). std::mem_fun permet de transformer ça en Element.Fonction(). Euuuh bon je suis pas un pro des explications claires alors je m'arrête là et te laisse décrouvrir la chose avec la doc et en essayant

    - Un foncteur est une classe pour laquelle on définit l'opérateur (), de sorte qu'on puisse utiliser ses instances comme des fonctions. Beaucoup de fonctions de la STL demandent (optionnellement) comme paramètre un foncteur ou une fonction globale, on préfère en général un foncteur pour des raisons d'inlinage et de flexibilité.

    Exemple : un foncteur (ici un prédicat) qui indique si un mot est égal à un mot prédéfini

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    struct IsEqual
    {
       IsEqual(const std::string& w) : Word(w) {}
       bool operator ()(const std::string& s) const
       {
          return s == Word;
       }
     
    private :
     
       std::string Word;
    }
    Ensuite avec ça par exemple on peut virer tous les mots égaux à un certain autre dans une séquence :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    std::vector<std::string> v;
    v.erase(std::remove_if(v.begin(), v.end(), IsEqual("toto")), v.end());

  7. #7
    Membre confirmé
    Inscrit en
    Septembre 2004
    Messages
    187
    Détails du profil
    Informations forums :
    Inscription : Septembre 2004
    Messages : 187
    Par défaut
    :pingoin: Bonsoir,
    Et merci pour toutes ces explications qui me promettent quelques heures de saines et studieuses lecture.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 13
    Dernier message: 20/10/2008, 21h16
  2. Erreur suite a conversion 2003 2008
    Par armin dans le forum Windows Forms
    Réponses: 2
    Dernier message: 22/08/2008, 16h31
  3. problème de conversion avec dateadd - suite et fin
    Par Bourezak dans le forum MS SQL Server
    Réponses: 1
    Dernier message: 31/01/2008, 13h57
  4. Réponses: 3
    Dernier message: 10/10/2007, 17h24

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo