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 :

utilisation de find_if


Sujet :

C++

  1. #1
    Inactif  

    Homme Profil pro
    Ingénieur test de performance
    Inscrit en
    Décembre 2003
    Messages
    1 986
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur test de performance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 1 986
    Par défaut utilisation de find_if
    J'ai une classe:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    class MaClass{
     
      public:
     
        int    iVal1;
        int    iVal2;
        string sz;
     
        bool operator () (int& i) { return ((*this).iVal2 == i); }
    };
    J'ai un vector de class:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    vector<MaClass> vClass;
    Le vector est ensuite rempli (je passe le code).

    J'aimerais utiliser l'algo find_if sur ce vector (mais il y a peut-être mieux), afin de trouver la classe dont la valeur iVal2 = 2.
    J'ai défini un objet fonction comme dans le code ci-dessus.

    Ce code ci-dessous ne fonctionne pas:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    vector::iterator it = find_if(vClass.begin(), vClass.end, MaClass()(2));
    Autant vous dire que je n'y comprends rien avec find_if et les foncteurs.
    Les exemples et les explications que je trouve sur le net ne me permettent pas d'utiliser correctement l'algo avec mon programme.

    L'erreur ici est: le terme ne correspond pas à une fonction qui prends les arguments 1.

    Si j'écris:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    vector::iterator it = find_if(vClass.begin(), vClass.end, MaClass(2));
    Conversion impossible.

    Merci de m'aider à comprendre.

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

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Par défaut
    Effectivement tu t'y prends mal

    Le foncteur doit être vu comme une fonction, il doit donc être séparé de ta classe. Là tu vas construire une instance de MaClass seulement pour utiliser l'opérateur (), qui en soi n'a rien à voir avec MaClass.
    Ensuite, les divers paramètres doivent être passés au constructeur de ton foncteur.
    Enfin, l'opérateur () doit prendre en paramètre un objet du type MaClass (ceux stockés dans ton vector).

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    struct MaClassEgal
    {
        MaClassEgal(int n) : nb(n);
     
        bool operator ()(const MaClass& m) const
        {
            return m.iVal2 == nb;
        }
     
    private :
     
        int nb;
    };
    Ensuite je vois que tu t'embrouilles avec les parenthèses. La chose à retenir est que tu dois passer une instance de ton foncteur :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    find_if(v.begin(), v.end(), MaClassEgal(2));
     
    // Ce qui peut être décomposé comme ceci :
     
    MaClassEgal f(2);
    find_if(v.begin(), v.end(), f);
    Parfois ça peut aider de voir comment ton foncteur va être utilisé, pour find_if ça doit être quelque chose de ce style :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    template <class ForwardIterator, class Func>
    ForwardIterator find_if(ForwardIterator begin, ForwardIterator end, Func f)
    {
        for (; begin != end; ++begin)
            if (f(*begin))
                return begin;
     
        return end;
    }

  3. #3
    Inactif  

    Homme Profil pro
    Ingénieur test de performance
    Inscrit en
    Décembre 2003
    Messages
    1 986
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur test de performance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 1 986
    Par défaut
    Merci LouLou24. Je rentre chez moi et je teste.


    PS: Une question sur ton tutorial "réalisation d'un moteur 3d en C++", partie 1.

    J'ai découvert un bug sur la classe qui gère les memoryleaks. Je t'explique la situation en privé ou comment je fais?

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

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Avril 2003
    Messages : 10 651
    Par défaut
    J'ai découvert un bug sur la classe qui gère les memoryleaks. Je t'explique la situation en privé ou comment je fais?
    Par MP ou par mail, ce sera parfait.

  5. #5
    Expert confirmé

    Homme Profil pro
    pdg
    Inscrit en
    Juin 2003
    Messages
    5 756
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : pdg

    Informations forums :
    Inscription : Juin 2003
    Messages : 5 756
    Billets dans le blog
    3
    Par défaut
    Tu peux être un peu plus dans l'esprit STL en modifiant MaClassEgal pour la rendre utilisable avec les réducteurs bind1st et bind2nd:
    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
     
    struct MaClassEgal : public binary_function<MaClass, int, bool> 
    { 
        bool operator()(const MaClass & m, int nb) const
        {
            return m.iVal2 == nb;
        }
    };
     
    vector<MaClass> v;
     
    find_if(
        v.begin(),
        v.end(),
        bind2nd( MaClassEgal(), 2 ) );
    bon c'est moins compréhensible au premier coup d'oeil. Mais c'est plus souple. Par exemple, pour faire la même recherche mais avec un objet Maclasse cette fois et dans un tableau d'entiers.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
        vector<int> v2;
        MaClass ma_classe_a_tester;
     
        find_if( 
            v2.begin(), 
            v2.end(), 
            bind1st( MaClassEgal(), ma_classe_a_tester ) );

  6. #6
    Inactif  

    Homme Profil pro
    Ingénieur test de performance
    Inscrit en
    Décembre 2003
    Messages
    1 986
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur test de performance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 1 986
    Par défaut
    Merci ça marche trop bien. Je n'aurais jamais pensé à créer une deuxième classe.

    Pour le bug je t'envoie l'explication par MP.

  7. #7
    Inactif  

    Homme Profil pro
    Ingénieur test de performance
    Inscrit en
    Décembre 2003
    Messages
    1 986
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur test de performance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 1 986
    Par défaut
    Aurelien.Regat-Barrel: si j'ai bien compris , ta méthode permet d'étendre la recherche de la valeur iVal2 de ma class avec d'autres objets qui n'ont rien à voir avec le vector de ma class (comme le vector d'entiers).

    Si c'est bien ça, alors oui ça peut être trop utile (et je vais m'en servir).

  8. #8
    Expert confirmé

    Homme Profil pro
    pdg
    Inscrit en
    Juin 2003
    Messages
    5 756
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : pdg

    Informations forums :
    Inscription : Juin 2003
    Messages : 5 756
    Billets dans le blog
    3
    Par défaut
    En fait non. C'est une autre écriture du code de Loulou. Au lieu de passer au constructeur l'entier à comparer et de le stocker dans la classe, il est passé en 2° paramètre de l'opérateur ().
    Avec le code de Loulou:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    MaClass c;
    MaClassEgal egal_a_2( 2 ); 
    if ( egal_a_2( c ) )
    {
        cout << "c.iVal2 == 2";
    }
    avec ma modification:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    MaClass c;
    MaClassEgal egal; 
    if ( egal( c, 2 ) )
    {
        cout << "c.iVal2 == 2";
    }
    ça, + le fait de la faire dériver de binary_function, ça permet de l'utiliser avec les réducteurs de la STL. Le code précedent devient:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    MaClass c;
    binder2nd<MaClassEgal> egal_a_2 = bind2nd( MaClassEgal(), 2 );
    if ( egal_a_2( c ) )
    {
        cout << "c.iVal2 == 2";
    }
    bon c'est illisible, mais on est pas censé utiliser de variable temporaire.
    bind2nd permet de fixer le 2° paramètre de l'opérateur (). En fait, bind2nd( MaClassEgal(), 2 ) permet de créer le même objet que dans la version de Loulou.
    Y'a aussi bind1st qui fixe le premier paramètre. Celui-ci est de type MaClass. Donc ça permet de réutiliser ton foncteur MaClassEgal pour comparer un object MaClass à un int, là ou jusque là on comparait un int à un objet MaClass.
    Bref, attend la prochaine mise à jour de la FAQ (d'ici 1 ou 2 semaines), y'a de nouvelles questions sur ce sujet.

  9. #9
    Inactif  

    Homme Profil pro
    Ingénieur test de performance
    Inscrit en
    Décembre 2003
    Messages
    1 986
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur test de performance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 1 986
    Par défaut
    Donc si j'ai bien compris cette fois , ça permet de comparer la valeur de mon objet avec n'importe quel autre objet du même type que ma valeur.

    C'est à double sens en quelque sorte.

    Heu il me semble que c'est ce que je pensais dans mon précédent poste

  10. #10
    Expert confirmé

    Homme Profil pro
    pdg
    Inscrit en
    Juin 2003
    Messages
    5 756
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : pdg

    Informations forums :
    Inscription : Juin 2003
    Messages : 5 756
    Billets dans le blog
    3
    Par défaut
    Si tu penses avoir compris ce que j'ai voulu te faire comprendre après avoir mal compris que tu n'avais pas bien compris ce que j'avais voulu te faire comprendre, alors c'est bon

  11. #11
    Inactif  

    Homme Profil pro
    Ingénieur test de performance
    Inscrit en
    Décembre 2003
    Messages
    1 986
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 50
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur test de performance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 1 986
    Par défaut
    Citation Envoyé par Aurelien.Regat-Barrel
    Si tu penses avoir compris ce que j'ai voulu te faire comprendre après avoir mal compris que tu n'avais pas bien compris ce que j'avais voulu te faire comprendre, alors c'est bon
    LOL, j'adore.

    Quand j'aurais utilisé bind1st et bind2nd, je verrais si j'ai bien compris ce que tu as voulu me faire comprendre alors que je n'étais pas sûr d'avoir compris ce que tu voulais me faire comprendre...

    +1

    Je crois que l'on s'est bien compris.


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

Discussions similaires

  1. utiliser les tag [MFC] [Win32] [.NET] [C++/CLI]
    Par hiko-seijuro dans le forum Visual C++
    Réponses: 8
    Dernier message: 08/06/2005, 15h57
  2. Réponses: 4
    Dernier message: 05/06/2002, 14h35
  3. utilisation du meta type ANY
    Par Anonymous dans le forum CORBA
    Réponses: 1
    Dernier message: 15/04/2002, 12h36
  4. [BCB5] Utilisation des Ressources (.res)
    Par Vince78 dans le forum C++Builder
    Réponses: 2
    Dernier message: 04/04/2002, 16h01
  5. Réponses: 2
    Dernier message: 20/03/2002, 23h01

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