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 :

Passer une fonction membre comme argument d'une fonction (ici de std::transform)


Sujet :

SL & STL C++

  1. #1
    Membre actif Avatar de Twindruff
    Inscrit en
    Janvier 2005
    Messages
    216
    Détails du profil
    Informations forums :
    Inscription : Janvier 2005
    Messages : 216
    Points : 237
    Points
    237
    Par défaut Passer une fonction membre comme argument d'une fonction (ici de std::transform)
    Bonjour,
    J'expose mon problème (je suis sous MSVC 8.0):

    • je possède plusieurs classes NoeudXXX qui dérivent toutes de la classe Noeud.
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      typedef Noeud* pNoeud;
      
      class Noeud
      {
      public:
      	// ...
      	virtual pNoeud clone(pNoeud pere) const;
      private:
      	// ...
      	pNoeud m_pere;
      }
      cette fonction membre clone est surchargée dans chaque classe dérivée et elle rend un pointeur sur une copie du Noeud. (La propriété m_pere du nouveau Noeud est fixée à pere).

    • J'ai une classe dérivée NoeudOperation
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      class NoeudOperation : public Noeud
      {
      public:
      	// ...
      private:
      	// ...
      	void copie(const NoeudOperation& droite);
      	pNoeud cloneur(pNoeud n);
      
      	// ...
      	vector<pNoeud> m_enfants;
      };
      La fonction membre privée copie me sert pour le constructeur de copie et pour l'opérateur =.
      Une partie de ma fonction copie est consacrée créer les clones des enfants et à les recopier dans le nouveau vecteur. Là je veux utiliser la fonction tranform des algorithmes de la STL (je pourrais faire autrement mais j'ai envie d'éclaircir l'affaire).

      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      pNoeud NoeudOperation::cloneur(pNoeud n)
      {
      	return n->clone(this);
      }
      
      void NoeudOperation::copie(const NoeudOperation& droite)
      {
      	// ...
      	m_enfants.clear(); // nécessaire ?
      	transform(droite.m_enfants.begin(), droite.m_enfants.end(), m_enfants.begin(), &NoeudOperation::cloneur);
      }
    • Mais à la compilation, vc me sort une erreur
      error C2064: term does not evaluate to a function taking 1 arguments
      sur
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      // TEMPLATE FUNCTION transform WITH UNARY OP
      template<class _InIt, class _OutIt, class _Fn1, class _InOutItCat>
      inline
      	_OutIt _Transform(_InIt _First, _InIt _Last, _OutIt _Dest, _Fn1 _Func,
      		_InOutItCat, _Range_checked_iterator_tag)
      	{	// transform [_First, _Last) with _Func
      	_DEBUG_RANGE(_First, _Last);
      	_DEBUG_POINTER(_Dest);
      	_DEBUG_POINTER(_Func);
      	for (; _First != _Last; ++_First, ++_Dest)
      		*_Dest = _Func(*_First);
      	return (_Dest);
      	}

    Merci à vous d'avance

  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
    Points : 15 920
    Points
    15 920
    Par défaut
    Il faut du code un peu plus chiadé ; regarde du côté de std::mem_fun_ref et std::bind2nd.

    Je crois qu'il y a des exemples dans la FAQ.

    A vue de nez, ta fonction cloneur devrait être const, sans quoi tu vas avoir des problèmes.

  3. #3
    Membre habitué Avatar de BigNic
    Profil pro
    Inscrit en
    Décembre 2004
    Messages
    195
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Décembre 2004
    Messages : 195
    Points : 154
    Points
    154
    Par défaut
    tu écris
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    template<class _InIt, class _OutIt, class _Fn1, class _InOutItCat>
    puis

    i
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    nline	_OutIt _Transform(_InIt _First, _InIt _Last, _OutIt _Dest, _Fn1 _Func,
    		_InOutItCat, _Range_checked_iterator_tag)
    enfin
    Donc tu déclare _func comme une classe et tu essayes de l'utiliser comme une fonction, ne serait-ce pas cela qui cloche ?

  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
    Points : 15 920
    Points
    15 920
    Par défaut
    Citation Envoyé par BigNic
    tu écris
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    template<class _InIt, class _OutIt, class _Fn1, class _InOutItCat>
    puis

    i
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    nline	_OutIt _Transform(_InIt _First, _InIt _Last, _OutIt _Dest, _Fn1 _Func,
    		_InOutItCat, _Range_checked_iterator_tag)
    enfin
    Donc tu déclare _func comme une classe et tu essayes de l'utiliser comme une fonction, ne serait-ce pas cela qui cloche ?
    Ca c'est le code de sa STL, et _Func est ce que l'on appelle un foncteur -- une classe qui se comporte comme une fonction.

  5. #5
    Membre actif Avatar de Twindruff
    Inscrit en
    Janvier 2005
    Messages
    216
    Détails du profil
    Informations forums :
    Inscription : Janvier 2005
    Messages : 216
    Points : 237
    Points
    237
    Par défaut
    Si j'ai bien compris tu me propose de modifier cloneur comme ça (sans parler du const)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    pNoeud NoeudOperation::cloneur(pNoeud n, pNoeud pere)
    {
    	return n->clone(pere);
    }
    et d'appeler
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    transform(droite.m_enfants.begin(), droite.m_enfants.end(), m_enfants.begin(),
        bind2nd(&NoeudOperation::cloneur, this));
    j'ai une bonne vingtaine d'erreurs avec ça

    Je vais peut-être tout simplement laisser cloneur à l'extérieur de la classe.

  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 : 40
    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
    Non, je ne te propose pas de modifier cloneur, mais de l'englober avec std::mem_fun_ref pour en faire un foncteur utilisable dans transform. D'ailleurs a priori tu n'as pas besoin de cette fonction intermédiaire.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    transform(droite.m_enfants.begin(), droite.m_enfants.end(), m_enfants.begin(), bind2nd(mem_fun_ref(&Noeud::clone), this));

  7. #7
    Membre actif Avatar de Twindruff
    Inscrit en
    Janvier 2005
    Messages
    216
    Détails du profil
    Informations forums :
    Inscription : Janvier 2005
    Messages : 216
    Points : 237
    Points
    237
    Par défaut
    Ah c'est joli ça

    Par contre c'est pas un bind1st qu'il faut ?
    J'obtiens ça finalement ( *this car il veut une référence )
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    transform(droite.m_enfants.begin(), droite.m_enfants.end(), m_enfants.begin(),
        bind1st(mem_fun_ref(&Noeud::clone), *this) );

  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 : 40
    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
    Avec bind1st tu vas avoir (*this).clone(m_enfants[i]).
    Avec bind2nd tu vas avoir m_enfants[i].clone(*this).

    Faut voir ce que tu veux.

    Ah c'est joli ça
    N'est-ce pas
    Par contre ça peut vite devenir plus illisible qu'une simple boucle. Si tu disposes de boost, avec boost::bind tu peux avoir une syntaxe un peu plus sympathique.

  9. #9
    Rédacteur

    Avatar de Matthieu Brucher
    Profil pro
    Développeur HPC
    Inscrit en
    Juillet 2005
    Messages
    9 810
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Développeur HPC
    Secteur : Industrie

    Informations forums :
    Inscription : Juillet 2005
    Messages : 9 810
    Points : 20 970
    Points
    20 970
    Par défaut
    ah oui, les _1, c'est le bonheur à comprendre

  10. #10
    Membre éclairé Avatar de HanLee
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    738
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Mai 2004
    Messages : 738
    Points : 871
    Points
    871
    Par défaut
    Juste pour savoir, tu veux faire quoi ? =)

    C'est pour ton TIPE ou tu t'amuses ?

  11. #11
    Membre actif Avatar de Twindruff
    Inscrit en
    Janvier 2005
    Messages
    216
    Détails du profil
    Informations forums :
    Inscription : Janvier 2005
    Messages : 216
    Points : 237
    Points
    237
    Par défaut
    Citation Envoyé par Laurent Gomila
    Avec bind1st tu vas avoir (*this).clone(m_enfants[i]).
    Avec bind2nd tu vas avoir m_enfants[i].clone(*this).
    Faut voir ce que tu veux.
    Tu avais raison, c'est donc bien un bind2nd dont j'avais besoin, je vais relire les exemples de la msdn.
    Mais encore quelque chose pourquoi utilises-tu mem_fun_ref plutôt que mem_fun.

    Citation Envoyé par Laurent Gomila
    Avec boost::bind tu peux avoir une syntaxe un peu plus sympathique.
    J'irais voir la doc de boost ok.

    Citation Envoyé par Miles
    ah oui, les _1, c'est le bonheur à comprendre


    Citation Envoyé par HanLee
    Juste pour savoir, tu veux faire quoi ? =)
    C'est pour ton TIPE ou tu t'amuses ?
    C'est un interpréteur d'expressions mathématiques. Il est "formel" évidemment pas au niveau de maple mais je gère variables, fonctions, etc.
    Et grande nouveauté les dérivées et les simplification simple .
    Au départ c'est un truc que j'avais fait l'année dernière pour m'amuser et puis comme je savais pas quoi faire comme TIPE je l'ai repris et amélioré

  12. #12
    Membre éclairé Avatar de HanLee
    Profil pro
    Inscrit en
    Mai 2004
    Messages
    738
    Détails du profil
    Informations personnelles :
    Âge : 37
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Mai 2004
    Messages : 738
    Points : 871
    Points
    871
    Par défaut
    Ah ok . Et oublie pas les primitives =P.
    T'aurais ptet du le faire en Caml/OCaml =).
    Tu t'en sors bien pour le parseur ? T'utilises boost::spirit ?

    Et sinon pour ta question :

    The result of calling mem_fun is a function object that takes a pointer to the element as its first argument. The result of calling mem_fun_ref is a function object that takes a reference to the element as its first argument.

  13. #13
    Rédacteur

    Avatar de Matthieu Brucher
    Profil pro
    Développeur HPC
    Inscrit en
    Juillet 2005
    Messages
    9 810
    Détails du profil
    Informations personnelles :
    Âge : 42
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : Développeur HPC
    Secteur : Industrie

    Informations forums :
    Inscription : Juillet 2005
    Messages : 9 810
    Points : 20 970
    Points
    20 970
    Par défaut
    Citation Envoyé par Twindruff
    Tu avais raison, c'est donc bien un bind2nd dont j'avais besoin, je vais relire les exemples de la msdn.
    Mais encore quelque chose pourquoi utilises-tu mem_fun_ref plutôt que mem_fun.
    mem_fun_ref proend en argument un X& tandis que mem_fun prend un X*

  14. #14
    Rédacteur/Modérateur
    Avatar de JolyLoic
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Août 2004
    Messages
    5 463
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 49
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Août 2004
    Messages : 5 463
    Points : 16 213
    Points
    16 213
    Par défaut
    Juste pour préciser que boost::bind est tellement plus simple à utiliser, qu'il a été accepté dans TR1, ce qui signifie qu'il a une très bonne chance de faire partie de la prochaine version du C++, et que certains développeurs de compilateurs sont en train de l'implémenter pour la prochaine version de leur compilo.
    Ma session aux Microsoft TechDays 2013 : Développer en natif avec C++11.
    Celle des Microsoft TechDays 2014 : Bonnes pratiques pour apprivoiser le C++11 avec Visual C++
    Et celle des Microsoft TechDays 2015 : Visual C++ 2015 : voyage à la découverte d'un nouveau monde
    Je donne des formations au C++ en entreprise, n'hésitez pas à me contacter.

  15. #15
    Membre actif Avatar de Twindruff
    Inscrit en
    Janvier 2005
    Messages
    216
    Détails du profil
    Informations forums :
    Inscription : Janvier 2005
    Messages : 216
    Points : 237
    Points
    237
    Par défaut
    Citation Envoyé par HanLee
    Ah ok . Et oublie pas les primitives =P.
    Heu non merci .

    Citation Envoyé par HanLee
    T'aurais ptet du le faire en Caml/OCaml =).
    C'est pour m'en servir dans d'autres programmes C++ que je l'ai fait.

    Citation Envoyé par HanLee
    Tu t'en sors bien pour le parseur ? T'utilises boost::spirit ?
    Ouais. Je n'utilise pas boost::spirit non.

    The result of calling mem_fun is a function object that takes a pointer to the element as its first argument. The result of calling mem_fun_ref is a function object that takes a reference to the element as its first argument.

    mem_fun_ref proend en argument un X& tandis que mem_fun prend un X*
    Oui j'ai bien vu la doc, mais justement dans le cas présent : les m_enfants sont des pointeurs. Et si j'ai bien compris:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    pNoeud x;
        bind2nd(mem_fun(&Noeud::clone), this)(x)
    <=> mem_fun(&Noeud::clone)(x, this)
    <=> x->clone(this)

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

Discussions similaires

  1. Réponses: 3
    Dernier message: 20/09/2013, 16h40
  2. Passer une Fonction comme argument d'une fonction
    Par ch16089 dans le forum Macros et VBA Excel
    Réponses: 1
    Dernier message: 27/02/2011, 17h58
  3. Réponses: 7
    Dernier message: 22/06/2008, 00h05
  4. @prompt comme argument d'une fonction
    Par putéolien dans le forum Deski
    Réponses: 7
    Dernier message: 27/11/2006, 14h09
  5. une url comme argument d'une fonction
    Par khayyam90 dans le forum Général JavaScript
    Réponses: 3
    Dernier message: 18/10/2004, 20h15

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