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

  1. #1
    Candidat au Club
    Utiliser la fonction transform dans une classe mère et définir l'unary fonction dans une classe fille
    Bonjour à tous,

    Voici mon premier message sur developpez.net. Mon problème est simple, j'ai une classe mère qui possède un vector en champ protégé et je souhaite définir une méthode qui utilise la fonction transform de la STL. Le code de cette méthode est quasiment le même pour toutes mes classes filles, la seule chose qui change est la fonction que prend transform en parametre. J'aimerai donc pouvoir définir cette fonction dans mes classes filles. C'est ici que ça bloque et malgré différents essais ça ne marche pas. Je vous présente deux petits exemples pour illustrer mon propos où dans les deux ça ne marche pas :

    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
     
    #include <vector>
    #include <algorithm>
     
    using namespace std;
     
    struct mere {
    	mere(int n) : value(n) {}
    	virtual int modif(int ) =0;
    	void prix() {
    		transform(value.begin(), value.end(), value.begin(), modif);
    	}
    	protected :
    		vector<int> value;
    };
     
    struct fille : public mere {
    	fille(int n, int K) : mere(n), K(K) {}
    	int modif(int x) { return K*x;}
    	private :
    		int K;
    };


    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
     
    #include <vector>
    #include <algorithm>
     
    using namespace std;
     
    struct mere {
    	mere(int n) : value(n), modif() {}
    	void prix() {
    		transform(value.begin(), value.end(), value.begin(), modif);
    	}
    	protected :
    		vector<int> value;
                    struct modif_value {
                            virtual int operator()(int );
                    } modif;
    };
     
    struct fille : public mere {
    	fille(int n, int K) : mere(n), K(K) , mK() {}
    	private :
    		int K;
                    struct modifK : public modif_value {
                            int operator()(int x) {return K*x;}
                    } mK;
    };


    Quelqu'un aurait t'il une solution? Par avance merci.

  2. #2
    Expert éminent sénior
    c'est normal, transform() attend une fonction libre, alors que tu lui donnes une fonction membre, ca ne peut pas marcher.

    Il doit y avoir une entrée dans la faq, je ne sais plus où, par contre

    La raison, c'est que transform n'a pas d'objet sur lequel appeler .modif().

    la solution est d'avoir un foncteur ou une lambda en C++11.
    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
     
    class modif_applier{
        mere& objet;
    public:
        modif_applier(mere& cible) : objet(cible) {}
        int operator(int n) const {return objet.modif(n);}
    }
     
    struct mere {
    	mere(int n) : value(n) {}
    	virtual int modif(int ) =0;
    	void prix() {
    		transform(value.begin(), value.end(), value.begin(), modifier(*this));
    	}
    	protected :
    		vector<int> value;
    };
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  3. #3
    Expert éminent sénior
    Sinon boost::bind ou std::binder1st (ou std::bind en C++11) peuvent être assez utiles pour transformer une méthode en une fonction.
    "Parce que le diable est dans les détails, une vision sans nuance ne peut prétendre à la compréhension du monde."

    Mon ancienne page perso : https://neckara.developpez.com/

  4. #4
    Expert éminent sénior
    Je n'ai pas le réflexe… c'est mieux, en effet
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  5. #5
    Candidat au Club
    Merci leternel pour ta réponse. J'ai donc essayé ta solution mais ça ne tourne toujours pas, voila le code avec ta solution :

    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
     
    #include <iostream>
    #include <vector>
    #include <algorithm>
     
    using namespace std;
     
    struct modifier {
            modifier(mere & cible) : objet(cible) {}
            int operator()(int n) const {return objet.modif(n);}
            private :
                    mere & objet;
    };
     
    struct mere {
            mere(int n) : value(n) {}
    	virtual int modif(int ) =0;
    	void prix() {
                    transform(value.begin(), value.end(), value.begin(), modifier(*this));
    	}
    	protected :
    		vector<int> value;
    };
     
    struct fille : public mere {
    	fille(int n, int K) : mere(n), K(K) {}
    	int modif(int x) { return K*x;}
    	private :
    		int K;
    };

  6. #6
    Expert éminent sénior
    C'est possible, je n'ai pas de compilateur C++ sous la main, j'ai fais de tête.
    Regarde la proposition de Neckara, c'est probablement mieux.

    Dans mon code, il doit te manquer une fonction libre telle que:
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    modifier create_modifier(mere& mere) {
        modifier m(mere);
        return m;
    }
    Mes principes de bases du codeur qui veut pouvoir dormir:
    • Une variable de moins est une source d'erreur en moins.
    • Un pointeur de moins est une montagne d'erreurs en moins.
    • Un copier-coller, ça doit se justifier... Deux, c'est un de trop.
    • jamais signifie "sauf si j'ai passé trois jours à prouver que je peux".
    • La plus sotte des questions est celle qu'on ne pose pas.
    Pour faire des graphes, essayez yEd.
    le ter nel est le titre porté par un de mes personnages de jeu de rôle

  7. #7
    Candidat au Club
    Le truc c'est que je ne maitrise pas la librairie boost et très peu (c'est un euphémisme) les fonctions de <functional>. C'est surement très puissant mais dans mon cas ça me semble un peu prendre un marteau pour écraser une mouche. Si je pouvais résoudre mon problème en utilisant simplement des structures ce serait parfait. Je n'ai pas réussi à faire tourner avec la fonction que tu proposes leternel.

  8. #8
    Expert éminent sénior
    Citation Envoyé par Vlntn Voir le message
    Le truc c'est que je ne maitrise pas la librairie boost et très peu (c'est un euphémisme) les fonctions de <functional>. C'est surement très puissant mais dans mon cas ça me semble un peu prendre un marteau pour écraser une mouche. Si je pouvais résoudre mon problème en utilisant simplement des structures ce serait parfait. Je n'ai pas réussi à faire tourner avec la fonction que tu proposes leternel.
    Sinon il faudrait faire quelque chose 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
    template<class U, class T, class V>
    class Functor
    {
                Functor(T class, V meth) : m_class(class), m_meth(meth){}
     
                U operator()( ... ) // on doit pouvoir jouer avec les va_list ou les templates <img src="images/smilies/aie.gif" border="0" alt="" title=":aie:" class="inlineimg" />
                {
                       return m_class->m_meth(...);
                 }
     
          private :
                T * m_class;
                V m_meth;
    }


    Mais personnellement, std::binder1st sera bien plus pratique.
    Après, les éléments de functionnal comme les algorithmes de la STL sont très puissants, mais ce ne sont en aucun cas des marteaux pour écraser une mouches.
    "Parce que le diable est dans les détails, une vision sans nuance ne peut prétendre à la compréhension du monde."

    Mon ancienne page perso : https://neckara.developpez.com/

  9. #9
    Candidat au Club
    Merci Neckara. Ca m'embête d'être trop insistant mais tu m'as convaincu, est t'il possible que tu me proposes une solution utilisant binder1st j'ai du mal à comprendre comment on l'utilise. Merci

  10. #10
    Expert éminent sénior
    ALors si je me souviens bien :
    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
    std::binder1st( fonction/méthode, premierArgument);
     
    // ex 1
    std::binder1st(maMethode, this);
     
    // ex 2
    MaClasse maClasse;
    std::binder1st(maMethode, &maClasse);
     
     
    int foo(int i, int j){ return i + j; }
     
    // ex 3
    std::binder1st(foo, 5);
     
    // ex 4
    std::binder1st(foo, 5)(2); // appelle le foncteur créé par binder1st avec 2 comme argument. Ce qui donnera 7.
    "Parce que le diable est dans les détails, une vision sans nuance ne peut prétendre à la compréhension du monde."

    Mon ancienne page perso : https://neckara.developpez.com/

  11. #11
    Candidat au Club
    Merci Neckara mais j'ai du mal à voir comment l'adapter à mon problème.

  12. #12
    Expert éminent sénior
    Tout simplement :
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    virtual int modif(int ) =0;
     
    void prix() {
         transform(value.begin(), value.end(),
                  value.begin(), std::binder1st(modif, this) );
    }
    "Parce que le diable est dans les détails, une vision sans nuance ne peut prétendre à la compréhension du monde."

    Mon ancienne page perso : https://neckara.developpez.com/

  13. #13
    Candidat au Club
    Merci Neckara mais lorsque je fais ça :

    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
     
    #include <vector>
    #include <algorithm>
    #include <functional>
     
    using namespace std;
     
    struct mere {
    	mere(int n) : value(n) {}
    	virtual int modif(int ) =0;
    	void prix() {
    		transform(value.begin(), value.end(), value.begin(), binder1st(modif, this) );
    	}
    	protected :
    		vector<int> value;
    };
     
    struct fille : public mere {
    	fille(int n, int K) : mere(n), K(K) {}
    	int modif(int x) { return K*x;}
    	private :
    		int K;
    };


    le compilateur me renvoie l'erreur suivante :
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
     
    In member function ‘void mere::prix()’:
    error: missing template arguments before ‘(’ token

  14. #14
    Expert éminent sénior
    Avec le C++11 et boost, je dois avouer que je n'utilise jamais std::binder1st, d'ailleurs, je me suis peut-être trompé, je pense que c'est std::bind1st :

    http://www.cplusplus.com/reference/functional/bind1st/
    "Parce que le diable est dans les détails, une vision sans nuance ne peut prétendre à la compréhension du monde."

    Mon ancienne page perso : https://neckara.developpez.com/