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

SL & STL C++ Discussion :

[std::list][find_if] problème avec mes foncteurs


Sujet :

SL & STL C++

  1. #1
    Membre éprouvé
    Avatar de n!co
    Profil pro
    Inscrit en
    Février 2004
    Messages
    831
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France

    Informations forums :
    Inscription : Février 2004
    Messages : 831
    Points : 936
    Points
    936
    Par défaut [std::list][find_if] problème avec mes foncteurs
    Bonjour à tous.

    Me voila devant un problème devant lequell je n'arrive pas a me dépatouiller.

    J'essaye de permettre une recherche sur les différents attributs de qqs objetcs stockés au sein d'une liste.

    Les prérequis :
    une classe toto
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    class toto {
        string nom;
        int age;
     
        // getters et setters
        ...
    }
    une liste de toto
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    std::list<toto> listToto;
    les foncteurs de recherche
    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
     
    struct rechercheNom {
    	rechercheNom(const string &s): nom(s) {}
        bool operator()(const Contact & obj1) const {
    		return obj1.getNom() == nom;
        }
    private:
    	string nom;
    }; 
     
    struct rechercheAge {
    	rechercheAge(const int&i): age(i) {}
        bool operator()(const Contact & obj1) const {
    		return obj1.getAge() == age;
        }
    private:
    	int age;
    };
    la fonction de recherche
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    template<class T> ListToto* ListToto::rechercherListe(int colonne, T critere) {
        switch(colonne) {
             // nom
             case 1 : find_if(listToto->begin(), listToto->end(), rechercheNom(critere));break;
             case 2 : find_if(listToto->begin(), listToto->end(), rechercheAge(critere);break;
        }
        // On ne s'occupe pas du retour pour le moment
        return this;
    }
    Dans l'état actuel, le code n'a pas l'air trop mal et le compilateur ne dit rien a la compilation.

    Mais voila un petit main rapide qui lui, pose problème au compilateur
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    main(void) {
        // Recherche du premier object ayant comme nom "nico"
        listToto.rechercherListe<string>(1, "nico");
        // Erreur : impossible de convertir 'string' en 'rechercheAge'
     
        // Recherche du premier object ayant comme age 20 ans
        listToto.rechercherListe<int>(2, 20);
        // Erreur : impossible de convertir 'int' en 'rechercheNom'
    }
    Donc voila, je comprend pourquoi le compilateur ne veut pas compiler, étant donné qu'il ne peut pas savoir a l'avance quelle sera la bonne methode appellée.
    Mais je ne trouve pas de solution alternative pour éviter ce problème.

    Je suis sur qu'un d'entre vous aura une bonne idée à tout cela
    Netbeans account : nico@share.java.net
    Merci de ne pas poser de questions techniques par MP

  2. #2
    Membre du Club
    Inscrit en
    Janvier 2005
    Messages
    36
    Détails du profil
    Informations forums :
    Inscription : Janvier 2005
    Messages : 36
    Points : 43
    Points
    43
    Par défaut
    je ne voit pas la mais ce n'est pas ton code complet minimal qui reproduise le probleme.... tu peux donner le tout pour pouvoir tester en local ?

  3. #3
    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 : 39
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Points : 15 920
    Points
    15 920
    Par défaut
    Effectivement là ça pose un problème de typage au compilo. Deux solutions je pense :

    - Si le numéro de colonne est toujours connu à la compilation, la solution sera de faire une fonction distincte pour chaque colonne ayant un type différent. En bidouillant un peu les templates tu pourras rendre ça un poil plus sympathique.

    - Si le numéro de colonne est une variable, alors il faudra peut-être passer par un type variant (boost::any par exemple) en paramètre et recaster dans le bon type selon le numero de colonne.

    Dans tous les cas il est clair que tu ne pourras pas compiler ce genre de code, le compilo ne peut pas savoir avant execution dans quelle case il devra passer.

  4. #4
    Membre du Club
    Inscrit en
    Janvier 2005
    Messages
    36
    Détails du profil
    Informations forums :
    Inscription : Janvier 2005
    Messages : 36
    Points : 43
    Points
    43
    Par défaut
    arf, bien vu loulou je viens de voir le probleme aussi....

    dans ton cas une solution a base d'un enum pour les colones et de traits fournissant les bon type/foncteur a utiliser permettrai d'eviter le switch, qqch du genre :

    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
     enum Colones {
      Nom,
      Age
    };
     
    template<Colones> struct ColTrait {};
     
    template<> struct ColTrait<Nom>
    {
      typedef std::string KeyType;
      typedef rechercheNom Fonctor;
    };
     
    template<> struct ColTrait<Age>
    {
      typedef int KeyType;
      typedef rechercheAge Fonctor;
    };
     
    template<class T> ListToto* ListToto::rechercherListe(const ColTrait<T>::KeyType& critere) 
    {
      ColTrait<T>::Fonctor func(critere);
      find_if(listToto->begin(), listToto->end(), func);
      return this;
    }
    (a l'arrache, pas teste)

  5. #5
    Nouveau membre du Club
    Homme Profil pro
    Ingénieur développement matériel électronique
    Inscrit en
    Février 2004
    Messages
    35
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement matériel électronique

    Informations forums :
    Inscription : Février 2004
    Messages : 35
    Points : 36
    Points
    36
    Par défaut
    Citation Envoyé par Loulou24
    Dans tous les cas il est clair que tu ne pourras pas compiler ce genre de code, le compilo ne peut pas savoir avant execution dans quelle case il devra passer.
    Salut Loulou, Je ne comprend pas bien pourquoi le compilo a besoin de savoir dans quel case il doit passer et donc pose un problème de trans-typage

  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 : 39
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Points : 15 920
    Points
    15 920
    Par défaut
    Citation Envoyé par onap
    Citation Envoyé par Loulou24
    Dans tous les cas il est clair que tu ne pourras pas compiler ce genre de code, le compilo ne peut pas savoir avant execution dans quelle case il devra passer.
    Salut Loulou, Je ne comprend pas bien pourquoi le compilo a besoin de savoir dans quel case il doit passer et donc pose un problème de trans-typage
    Au moment de la compilation, le compilo ne peut pas connaitre les futures valeurs de Colonne et donc quel code sera appelé. Donc il compile toute la fonction, et c'est seulement lors de l'execution que tel ou tel code sera appelé selon la valeur du paramètre.

  7. #7
    Membre éprouvé
    Avatar de n!co
    Profil pro
    Inscrit en
    Février 2004
    Messages
    831
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France

    Informations forums :
    Inscription : Février 2004
    Messages : 831
    Points : 936
    Points
    936
    Par défaut
    [quote="Loulou24"][quote="onap"]
    Citation Envoyé par Loulou24
    Au moment de la compilation, le compilo ne peut pas connaitre les futures valeurs de Colonne et donc quel code sera appelé. Donc il compile toute la fonction, et c'est seulement lors de l'execution que tel ou tel code sera appelé selon la valeur du paramètre.
    Me revoila

    Exact
    J'avais calculé ce détail, mais la solution pour y remédier ...
    Je ne conaissais pas le type variant et y a fort a parier qu'il est implété dans le code de dok3
    Je me panche la dessus de suite
    Netbeans account : nico@share.java.net
    Merci de ne pas poser de questions techniques par MP

  8. #8
    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 : 39
    Localisation : France, Moselle (Lorraine)

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Points : 15 920
    Points
    15 920
    Par défaut
    Il n'y a pas de type variant en standard, mais il en existe quelques bons (au pire cela revient à faire du void*, mais autant encapsuler ça du mieux possible pour garder un typage fort).

    Quant à la solution de dok3, c'est celle qui suppose que la colonne sera toujours connue à la compilation et qui choisit donc le bon code à appeler directement (via les templates), ce n'est donc pas du tout la même chose .

    D'ailleurs il serait utile que tu précises si oui ou non ces numéros de colonne seront connus à la compilation ou à l'execution.

  9. #9
    Membre éprouvé
    Avatar de n!co
    Profil pro
    Inscrit en
    Février 2004
    Messages
    831
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France

    Informations forums :
    Inscription : Février 2004
    Messages : 831
    Points : 936
    Points
    936
    Par défaut
    Oui excuse moi, je n'ai pas fait de mise en situation.

    L'objectif est de gérer un carnet d'adresse.
    Chaque contact est représenté par un objet et défini par son nom, prenom, adresse, ...
    La liste des contact est stockée dans une liste chainée (std::list)
    Parmis les fonctionnalités du carnet, il faut permettre une recherche des contacts sur tous les attribus.

    Dans l'exemple du dessus, la colonne est un attibut de mon contact, donc le compilo ne peut pas connaitre sa valeur a la compilation
    Si on n'utilise plus le switch, il n'y a plus de choix donc plus de problème a la compilation non ? (cf. code dok3)
    Enfin de toute facon, faut que je regarde ce que sont les types variants.
    Venant du Java, j'ai un peu de mal avec l'immensité du C++, mais je vais mi faire

    En tout cas merci beucoup à tous le deux
    Netbeans account : nico@share.java.net
    Merci de ne pas poser de questions techniques par MP

  10. #10
    Membre du Club
    Inscrit en
    Janvier 2005
    Messages
    36
    Détails du profil
    Informations forums :
    Inscription : Janvier 2005
    Messages : 36
    Points : 43
    Points
    43
    Par défaut
    Si on n'utilise plus le switch, il n'y a plus de choix donc plus de problème a la compilation non ? (cf. code dok3)
    Avec mon exemple tu doit donner la colonne a la compilation, impossible d'utiliser une valeur d'enum non connue a la compilation pour instancier la fonction template.

  11. #11
    Membre éprouvé
    Avatar de n!co
    Profil pro
    Inscrit en
    Février 2004
    Messages
    831
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France

    Informations forums :
    Inscription : Février 2004
    Messages : 831
    Points : 936
    Points
    936
    Par défaut
    D'apres ce que je viens de voir, le type VARIANT est fortement lié à windows et la communication avec des objets OLE.
    Il y aussi le boost::any qui necesite l'utilisation d'une bibliotheque supplémentaire.

    La je suis un peu pommer dans tout cela.
    J'aimerais dépendre le moins possible de bibliotheque ou environnement de développement.

    Il me faudrait trouver un moyen d'utiliser autrement mes foncteurs.
    Netbeans account : nico@share.java.net
    Merci de ne pas poser de questions techniques par MP

  12. #12
    Membre du Club
    Inscrit en
    Janvier 2005
    Messages
    36
    Détails du profil
    Informations forums :
    Inscription : Janvier 2005
    Messages : 36
    Points : 43
    Points
    43
    Par défaut
    boost::any c'est du template only, donc tu as juste a inclure le header qui va bien, rien de special a rajouter au link et de plus boost deviens de plus en plus incontournable

    a titre d'exemple, sur les fedora core 2 boost est installer d'office quand tu install les dev tools

    apres si tu ne peux rien avoir de connu a la compilation, que tu ne veux pas de variant , que tu ne veux pas de void* static_caster a la brute ... alors tu fait une fonction de recherche par colonne ...

    autre solution, un seul foncteur avec comme parametre de recherche un objet representant ta "requette". on peut imaginer un objet du genre :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    struct ToSeek
    {
        bool seekAge;
        int ageToSeek;
     
        bool seekNom;
        string nomToSeek;
    };
    et un foncteur:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    struct SeekLe
    {
        ToSeek toSeek;
     
        bool operator==(const Toto& toto)
        {
              if (toSeek.seekNom && toto.name()==toSeek.nom)
                   return true;
              ..........
        }
    };

  13. #13
    Membre éprouvé
    Avatar de n!co
    Profil pro
    Inscrit en
    Février 2004
    Messages
    831
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France

    Informations forums :
    Inscription : Février 2004
    Messages : 831
    Points : 936
    Points
    936
    Par défaut
    Boost vient de finir de s'installer.
    Je vais pouvoir me plonger plus en detail la dedans.

    En plus ya même la gestion de la sérialisation, j'en suis doublement content
    Netbeans account : nico@share.java.net
    Merci de ne pas poser de questions techniques par MP

Discussions similaires

  1. [AJAX] Listes liées avec Ajax
    Par Zak_92 dans le forum Général JavaScript
    Réponses: 10
    Dernier message: 15/08/2007, 12h19
  2. [Liste Modifiable] Problème avec la valeur par défault
    Par fusion_sadam dans le forum Access
    Réponses: 3
    Dernier message: 16/06/2006, 11h00
  3. problème avec mes constantes
    Par salseropom dans le forum C
    Réponses: 6
    Dernier message: 10/05/2006, 17h37
  4. [JDBC]problème avec mes id
    Par Hydre dans le forum JDBC
    Réponses: 12
    Dernier message: 29/09/2005, 13h19
  5. Problème avec mes tables de relation...
    Par mmike dans le forum PostgreSQL
    Réponses: 4
    Dernier message: 02/06/2003, 15h16

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