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 :

Utiliser la fonction transform dans une classe mère et définir l'unary fonction dans une classe fille


Sujet :

SL & STL C++

  1. #1
    Candidat au Club
    Profil pro
    Inscrit en
    Mai 2013
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2013
    Messages : 7
    Points : 2
    Points
    2
    Par défaut 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

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 186
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 186
    Points : 17 126
    Points
    17 126
    Par défaut
    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
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 012
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2011
    Messages : 9 012
    Points : 23 209
    Points
    23 209
    Par défaut
    Sinon boost::bind ou std::binder1st (ou std::bind en C++11) peuvent être assez utiles pour transformer une méthode en une fonction.

  4. #4
    Expert éminent sénior

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 186
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 186
    Points : 17 126
    Points
    17 126
    Par défaut
    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
    Profil pro
    Inscrit en
    Mai 2013
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2013
    Messages : 7
    Points : 2
    Points
    2
    Par défaut
    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

    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Juin 2007
    Messages
    5 186
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Juin 2007
    Messages : 5 186
    Points : 17 126
    Points
    17 126
    Par défaut
    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
    Profil pro
    Inscrit en
    Mai 2013
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2013
    Messages : 7
    Points : 2
    Points
    2
    Par défaut
    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
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 012
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2011
    Messages : 9 012
    Points : 23 209
    Points
    23 209
    Par défaut
    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 :aie:
                {
                       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.

  9. #9
    Candidat au Club
    Profil pro
    Inscrit en
    Mai 2013
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2013
    Messages : 7
    Points : 2
    Points
    2
    Par défaut
    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
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 012
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2011
    Messages : 9 012
    Points : 23 209
    Points
    23 209
    Par défaut
    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.

  11. #11
    Candidat au Club
    Profil pro
    Inscrit en
    Mai 2013
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2013
    Messages : 7
    Points : 2
    Points
    2
    Par défaut
    Merci Neckara mais j'ai du mal à voir comment l'adapter à mon problème.

  12. #12
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 012
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2011
    Messages : 9 012
    Points : 23 209
    Points
    23 209
    Par défaut
    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) );
    }

  13. #13
    Candidat au Club
    Profil pro
    Inscrit en
    Mai 2013
    Messages
    7
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2013
    Messages : 7
    Points : 2
    Points
    2
    Par défaut
    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
    Inactif  


    Homme Profil pro
    Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Inscrit en
    Décembre 2011
    Messages
    9 012
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 30
    Localisation : France, Loire (Rhône Alpes)

    Informations professionnelles :
    Activité : Doctorant sécurité informatique — Diplômé master Droit/Économie/Gestion
    Secteur : Enseignement

    Informations forums :
    Inscription : Décembre 2011
    Messages : 9 012
    Points : 23 209
    Points
    23 209
    Par défaut
    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/

Discussions similaires

  1. Réponses: 1
    Dernier message: 20/09/2013, 11h02
  2. Réponses: 4
    Dernier message: 14/12/2011, 16h58
  3. Réponses: 7
    Dernier message: 05/04/2011, 18h19
  4. Typedef dans une classe mère template
    Par Mat007 dans le forum Langage
    Réponses: 2
    Dernier message: 23/09/2009, 11h50
  5. Réponses: 2
    Dernier message: 10/11/2006, 20h57

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