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 :

STL et prédicat


Sujet :

SL & STL C++

  1. #1
    Membre averti
    Inscrit en
    Décembre 2007
    Messages
    30
    Détails du profil
    Informations forums :
    Inscription : Décembre 2007
    Messages : 30
    Par défaut STL et prédicat
    Bonjour,
    j'utilise le containeur list de la STL contenant plusieurs éléments de la classe suivante :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    class position
    {
    public:
    	int l, m , n;
    	double x;
    	double y;
    	double z;
    }
    Je souhaite supprimer certains éléments de la liste que j'ai créé suivant un critère par exemple n = variable . J'essaie d'utiliser l'algorithme remove_if mais il demande un predicate. Pouvez vous m'aider à comprendre comment marche les prédicats ?
    je regardais sur beaucoup de site et je n'arrive toujours pas a supprimer un élément.
    Je vous remercie d'avance pour votre aide.

  2. #2
    Membre averti
    Inscrit en
    Décembre 2007
    Messages
    30
    Détails du profil
    Informations forums :
    Inscription : Décembre 2007
    Messages : 30
    Par défaut
    Certains parlent d'utiliser bind2nd() ou bind1st(). Quel est la différence ? Comment les utilise-t-on ?
    Si quelqu'un avez plus de renseignement ca serait sympa.

  3. #3
    Invité(e)
    Invité(e)
    Par défaut
    Bonjour,

    On peut voir un prédicat une fonction booléenne qui prend le type stocké dans la liste comme paramètre.

    Il faut donc que tu donnes à remove_if une fonction comme :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    bool mon_predicat(const position & pos) {
        /* on supprime si n est égal à zero. */
        return (pos.n == 0);
    }
    http://www.cplusplus.com/reference/stl/list/remove_if/

    Pour les bind, voir ce tuto http://r0d.developpez.com/articles/algos-stl/#LI-D

  4. #4
    Membre averti
    Inscrit en
    Décembre 2007
    Messages
    30
    Détails du profil
    Informations forums :
    Inscription : Décembre 2007
    Messages : 30
    Par défaut
    En fait, je cherche plutôt une fonction comme ca :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    bool mon_predicat(const position & pos, int ma_variable) {
        /* on supprime si n est égal à zero. */
        return (pos.n == ma_variable);
    }
    J'ai cru comprendre qu'un prédicat est une fonction unaire:
    predicate
    Unary predicate that, taking a value of the same type as those contained in the list object, returns true for those values to be removed from the container, and false for those remaining.


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     endp = remove_if(list1.begin(), list1.end(),bind2nd(greater<int>(), variable));
    En fait, l'utilisation bind2nd ou bind1st permet d'ajouter un paramètre supplémentaire ce qui serait assez pratique.

  5. #5
    Invité(e)
    Invité(e)
    Par défaut
    En fait, je cherche plutôt une fonction comme ca :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    bool mon_predicat(const position & pos, int ma_variable) {
        /* on supprime si n est égal à zero. */
        return (pos.n == ma_variable);
    }
    Alors, dans ce cas, il ne faut pas passer par un prédicat fonction, mais par une classe :
    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
    struct predicat{
        predicat(int var) {
            ma_variable = var;
        }
        int ma_variable;
        bool operator () (const position & pos) {
            return (pos.n == ma_variable);
        }
    };
     
    int main() 
    {
        predicat mon_predicat(5);
     
        list<position> ma_liste;
     
        ma_liste.remove_if(mon_predicat);
     
        return 0;
    }
    Si on tiens absolument à utiliser bind1st ou bind2nd, il faut implémenter une binary_function, mais je pense que le comportement final est à peut près équivalent.

  6. #6
    Rédacteur
    Avatar de 3DArchi
    Profil pro
    Inscrit en
    Juin 2008
    Messages
    7 634
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2008
    Messages : 7 634
    Par défaut
    Salut,
    std::ptr_fun permet de créer un foncteur avec une fonction libre.
    std::bind2nd permet de lier le second paramètre du foncteur.
    Ce qui donnerait :
    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
    #include <list>
    #include <algorithm>
    #include <functional>
     
    class position
    {
    public:
    	int l, m , n;
    	double x;
    	double y;
    	double z;
    };
     
    bool mon_predicat(position  pos, int ma_variable) {
        /* on supprime si n est égal à zero. */
        return (pos.n == ma_variable);
    }
     
    int main()
    {
       std::list<position> lst_pos;
       std::remove_if(
          lst_pos.begin(),
          lst_pos.end(),
          std::bind2nd(std::ptr_fun(&mon_predicat),42)
       );
       return 0;
    }
    Malheureusement, ça capture mal la référence constante du premier paramètre, donc un passage par valeur est nécessaire.
    Sinon, avec boost, ça se passe mieux :
    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
    #include <list>
    #include <algorithm>
    #include "boost\bind.hpp"
     
    class position
    {
    public:
    	int l, m , n;
    	double x;
    	double y;
    	double z;
    };
     
    bool mon_predicat(position const& pos, int ma_variable) {
        /* on supprime si n est égal à zero. */
        return (pos.n == ma_variable);
    }
     
    int main()
    {
       std::list<position> lst_pos;
       std::remove_if(
          lst_pos.begin(),
          lst_pos.end(),
          boost::bind(mon_predicat,_1,42)
       );
       return 0;
    }
    Sinon, il reste effectivement la possibilité proposée par Mabu de passer par une structure dédiée :
    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
    31
    #include <list>
    #include <algorithm>
     
    class position
    {
    public:
    	int l, m , n;
    	double x;
    	double y;
    	double z;
    };
    struct mon_predicat
    {
       int ma_variable;
       mon_predicat(int var_):ma_variable(var_){}
       bool operator()(position const& pos) {
           /* on supprime si n est égal à zero. */
           return (pos.n == ma_variable);
       }
    };
     
    int main()
    {
       std::list<position> lst_pos;
       std::remove_if(
          lst_pos.begin(),
          lst_pos.end(),
          mon_predicat(42)
       );
       return 0;
    }
    P.S. C++0x devrais même te faciliter la vie avec les lambdas (non testé mais ça devrait y ressembler peu ou prou) :
    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 <list>
    #include <algorithm>
     
    class position
    {
    public:
    	int l, m , n;
    	double x;
    	double y;
    	double z;
    };
     
    int main()
    {
       std::list<position> lst_pos;
       std::remove_if(
          lst_pos.begin(),
          lst_pos.end(),
          [](position const& pos){return (pos.n == 42);}
       );
     
       return 0;
    }

  7. #7
    Membre éclairé
    Inscrit en
    Avril 2005
    Messages
    1 110
    Détails du profil
    Informations forums :
    Inscription : Avril 2005
    Messages : 1 110
    Par défaut
    Citation Envoyé par 3DArchi Voir le message
    Malheureusement, ça capture mal la référence constante du premier paramètre, donc un passage par valeur est nécessaire.
    Je me permet un petit HS
    J'ai un peu "complété" la STL pour contourner ce problème endémique (pour les méthodes de classe)
    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
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    		// TEMPLATE CLASS binder2nd
    template<class _Bfn>
    class binder2nd_mod: public std::unary_function<typename _Bfn::first_argument_type, typename _Bfn::result_type>
    {
    protected:
    	_Bfn op;
    	typename _Bfn::second_argument_type value;
    public:
    	binder2nd_mod(_Bfn _X, typename _Bfn::second_argument_type _Y)
    		: op(_X), value(_Y) {}
    	result_type operator()(const argument_type & _X) const
    		{ return (op(_X, value)); }
    };
    		// TEMPLATE FUNCTION bind2nd
    template<class _Bfn, class _Ty>
    inline binder2nd_mod<_Bfn> bind2nd_mod(_Bfn _X, const _Ty & _Y)
    	{ return (binder2nd_mod<_Bfn>(_X,_Y)); }
     
     
    template<class _Result, class _Ty, class _Arg>
    class const_mem_fun1_ref_mod_t: public std::binary_function<_Ty, _Arg, _Result>
    {	// functor adapter (*left.*pfunc)(val), const *pfunc
    private:
    	_Result (_Ty::*_Pmemfun)(_Arg) const;	// the member function pointer
    public:
    	explicit const_mem_fun1_ref_mod_t(_Result (_Ty::*_Pm)(_Arg) const)
    		: _Pmemfun(_Pm) // construct from pointer
    		{}
     
    	_Result operator()(const _Ty & _Left, _Arg _Right) const
    		{	// call function with operand
    		return ((_Left.*_Pmemfun)(_Right));
    		}
    };
     
    template<class _Result, class _Ty, class _Arg>
    inline const_mem_fun1_ref_mod_t<_Result, _Ty, _Arg> mem_fun_ref_mod(_Result (_Ty::*_Pm)(_Arg) const)
    	{	// return a const_mem_fun1_ref_t functor adapter
    	return (const_mem_fun1_ref_mod_t<_Result, _Ty, _Arg>(_Pm));
    	}
    Il ne faut ans doute pas grand chose de plus pour utilisation avec les fonctions libres.

  8. #8
    Membre averti
    Inscrit en
    Décembre 2007
    Messages
    30
    Détails du profil
    Informations forums :
    Inscription : Décembre 2007
    Messages : 30
    Par défaut
    Je vous remercie vraiment pour votre aide. Vos solutions me semblent toutes très intéressante.
    Je vais finir par éplucher ca demain matin (il se fait un peu tard ici).

    Merci mille fois !

  9. #9
    Membre Expert
    Avatar de Joel F
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Septembre 2002
    Messages
    918
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur en informatique
    Secteur : Service public

    Informations forums :
    Inscription : Septembre 2002
    Messages : 918
    Par défaut
    @Archi3D, pour rester avec Boost, une boost::lambda est tout aussi simple (voir un coup de Phoenix)

  10. #10
    Expert éminent
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 644
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 53
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 644
    Par défaut
    Salut,

    Allez, pour rajouter une dernière possibilité...

    Si la valeur avec laquelle tu veux effectuer la comparaison est une valeur numérique entière(ou considérable comme telle), tu peux également envisager la création d'une fonction template:
    template <int i>
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    bool predicat(position const & p)
    {
        return p.n==i;
    }
    qui s'utiliserait sous la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    int main()
    {
        std::list<position> l_pos;
        /* ...*/
        std::remove_if(l_pos.begin(), l_pos.end(),predicat<5>);
        return 0;
    }
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  11. #11
    Membre Expert
    Avatar de Goten
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    1 580
    Détails du profil
    Informations personnelles :
    Âge : 35
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 1 580
    Par défaut
    Citation Envoyé par Joel F Voir le message
    @Archi3D, pour rester avec Boost, une boost::lambda est tout aussi simple (voir un coup de Phoenix)
    Y'a-t-il encore une raison d'utiliser lambda? Je vois plus ça comme quelque chose de deprecated au profit de phoenix. (et il me semble que je suis pas le seul!)

  12. #12
    Membre Expert
    Avatar de Joel F
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Septembre 2002
    Messages
    918
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur en informatique
    Secteur : Service public

    Informations forums :
    Inscription : Septembre 2002
    Messages : 918
    Par défaut
    Phoenix est parfois lourd en temps de compilation, mais oui on pousse avec Harmut et l'aute Joel pr passer Phoenix en first class citizen.

  13. #13
    Membre Expert
    Avatar de Goten
    Profil pro
    Inscrit en
    Juillet 2008
    Messages
    1 580
    Détails du profil
    Informations personnelles :
    Âge : 35
    Localisation : France

    Informations forums :
    Inscription : Juillet 2008
    Messages : 1 580
    Par défaut
    Ah oui, lourd, c'est pas faux. (chose qui devrait être améliorer avec le passage à proto non?)

  14. #14
    Membre Expert
    Avatar de Joel F
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Septembre 2002
    Messages
    918
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Chercheur en informatique
    Secteur : Service public

    Informations forums :
    Inscription : Septembre 2002
    Messages : 918
    Par défaut
    Oui. Dans un des prototypes qu'on teste, j'en ai un qui remplacent les actor (objet) par des fonctions qui appellent make_expr. J'avais posté ici:

    http://lists.boost.org/boost-users/2009/02/45591.php

    une analyse des temps de compils respectifs d'objet vs fonctions.
    Restera les 2.2s de preprocessing de proto

  15. #15
    Membre averti
    Inscrit en
    Décembre 2007
    Messages
    30
    Détails du profil
    Informations forums :
    Inscription : Décembre 2007
    Messages : 30
    Par défaut
    Je vous remercie pour votre aide. Ca a parfaitement résolu mon probleme mais maintenant je dois m'attaquer aux différents bugs qu'il y a dans mon programme...
    Encore une fois merci à vous.

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

Discussions similaires

  1. problème de références _ptr dans une map STL
    Par Mr_Tyu dans le forum CORBA
    Réponses: 1
    Dernier message: 10/08/2004, 11h39
  2. STL::vector crash a l"execution
    Par sebA dans le forum MFC
    Réponses: 2
    Dernier message: 16/06/2004, 17h36
  3. Probleme de Compilation de la STL
    Par stoluup dans le forum MFC
    Réponses: 3
    Dernier message: 05/05/2004, 18h25
  4. STL : std::set problème avec insert ...
    Par Big K. dans le forum MFC
    Réponses: 13
    Dernier message: 08/11/2003, 02h02
  5. [Kylix] [BCB] pb avec la STL
    Par pykoon dans le forum EDI
    Réponses: 1
    Dernier message: 29/12/2002, 13h56

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