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

Boost C++ Discussion :

spirit et phoenix::bind


Sujet :

Boost C++

  1. #1
    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 spirit et phoenix::bind
    Bonjour,
    Je souhaite créer un functor sur repeat_p sans grand succès!
    Sous visual, la ligne suivante fonctionne sans problème:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    phoenix::bind(&boost::spirit::repeat_p<size_t>)
    Par contre, avec gcc, j'obtiens l'erreur suivante:
    error: no matching function for call to `bind(<unknown type>)'
    Quelqu'un aurait une idée?
    Merci.
    Code complet:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    #include <boost/spirit.hpp>
    #include <boost/spirit/phoenix.hpp>
    using namespace BOOST_SPIRIT_CLASSIC_NS;
    using namespace phoenix;
     
    #include <iostream>
    int main()
    {
       phoenix::bind(&boost::spirit::repeat_p<size_t>);
       return std::getc(stdin);
    }

  2. #2
    Alp
    Alp est déconnecté
    Expert confirmé

    Avatar de Alp
    Homme Profil pro
    Inscrit en
    Juin 2005
    Messages
    8 575
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Juin 2005
    Messages : 8 575
    Par défaut
    http://www.boost.org/doc/libs/1_35_0...doc/loops.html
    Je ne crois pas que tu puisse juste binder repeat_p<size_t>...

    Si tu veux faire ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    boost::spirit::repeat_p<size_t>(ici tu ne veux pas encore donner de valeur)[le_motif_a_repeter_que_tu_connais_deja]
    Je te conseille de wrapper tout ça dans une classe repeat à toi qui connaitrais déjà le motif et n'aurais donc plus qu'à appeler () et à y joindre le motif... Avec le principe de foncteur, tu pourras garder un comportement d'évaluation tardive si tu fais un bind sur ton wrapper.

    Enfin, si j'ai bien compris ton problème

  3. #3
    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
    En fait, c'est déjà ce que j'ai fait. Mais, ça ne compile pas à cause de çà. Ou plutôt ça compile en visual mais pas en gcc. J'ai réduit à la ligne minimale pour voir.
    Voici le code complet:
    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
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    #include <boost/spirit.hpp>
    #include <boost/spirit/dynamic/lazy.hpp>
    #include <boost/spirit/phoenix.hpp>
    using namespace BOOST_SPIRIT_CLASSIC_NS;
    using namespace phoenix;
     
    // actor pour la creation de règles paramétrées par 1 argument:
    template<typename TRetour, typename TLazyRegle, typename TArg>
    struct regle_lazy
    {
       template<class Tuple> struct result {typedef TRetour type;};
       regle_lazy(TLazyRegle P_regle,TArg& P_arg):m_regle(P_regle),m_arg(P_arg)
       {
       }
       TRetour operator()()const
       {// on appele la regle avec l'évaluation de l'argument
          return m_regle(m_arg());
       }
    protected:
       TLazyRegle m_regle;
       TArg& m_arg;
    };
    // méthode pour construire facilement une règle_lazy:
    template<class TRetour, class TRegle, class TArg>
    regle_lazy<TRetour,TRegle,TArg> regle_lazy_p(const TRegle &P_regle, TArg&P_arg)
    {
       return regle_lazy<TRetour, TRegle, TArg>(P_regle,P_arg);
    }
     
    class MaGrammaire
       :public grammar<MaGrammaire>
    {
    public:
       // définition de la structure closure pour les variables associées aux règles:
       struct variable_taille : boost::spirit::closure<variable_taille, size_t>
       {
         member1 NbrElts;
       };
     
       template <typename ScannerT>
       struct definition
       {
     
     
          // définition de la grammaire:
          definition(MaGrammaire const& self)
          {
             liste             = uint_p[liste.NbrElts=arg1]>>":">>lire_liste;
             lire_liste        = lazy_p( regle_lazy_p<rule<ScannerT> >(
                      phoenix::bind(&fixed_loop_gen<size_t>::operator[]<rule<ScannerT> >)(phoenix::bind(&repeat_p<size_t>)(arg1),var(element))
                      ,liste.NbrElts
                   )
                );
             element           = uint_p>>",";
          }
     
          // définition de la racine:
          rule<ScannerT,typename variable_taille::context_t> const& start() const
             {return liste;}
       protected:
          // les règles:
          rule<ScannerT,typename variable_taille::context_t> liste;
          rule<ScannerT> element;
          rule<ScannerT> lire_liste;
     
       };
    };
     
    #include <iostream>
    int main()
    {
       MaGrammaire MonParseur;
     
       std::string L_strChaine("6:1,2,3,4,5,6,");
       parse_info<char const*> info = parse(
            L_strChaine.c_str(),
            L_strChaine.c_str()+L_strChaine.length(),
            MonParseur
        );
        if (info.full)
            std::cout << "Parse succeeded!\n";
        else
            std::cout << "Parse failed!\n";
       return std::getc(stdin);
    }

  4. #4
    Alp
    Alp est déconnecté
    Expert confirmé

    Avatar de Alp
    Homme Profil pro
    Inscrit en
    Juin 2005
    Messages
    8 575
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations forums :
    Inscription : Juin 2005
    Messages : 8 575
    Par défaut
    C'est
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    (phoenix::bind(&repeat_p<size_t>)(arg1)
    qui n'est pas bon.

    Tu dois wrapper le repeat_p<size_t> dans une structure ou quoi, cf mon message ci-dessus. Et c'est cette structure que tu devras binder !

  5. #5
    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
    C'est ce que j'avais commencer à faire (cf mon autre post). Mon soucis était plutôt d'évaluer un argument au bon moment. Du coup, j'ai essayé de généraliser (un peu) mon wrapper en enlevant la partie spécifique du repeat_p pour en faire un wrapper d'une règle paramétrée par un arg. D'où le nouveau code, mais c'est un échec... Du coup, il me faudrait un wrapper pour repeat_p et un autre pour son évaluation. Bon, je vais réfléchir pour voir comment faire au plus simple.
    P.S. Le lien sur boost renvoie à la doc boost_35 -> on est en 36. Bon, je penses pas que ça change grand chose...
    P.P.S.: Le problème est que la doc ne donne que des exemples avec des valeurs en durs ou à partir d'une variable. Moi, j'aimerais utiliser les closure pour récupérer la valeur avant de l'injecter dans la règle. Le pb alors c'est de n'évaluer la closure qu'au moment où la règle est évaluée.

  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
    Bon c'est ce que j'ai fait: un wrapper sur repeat_p:
    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
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    #include <boost/spirit.hpp>
    #include <boost/spirit/dynamic/lazy.hpp>
    #include <boost/spirit/phoenix.hpp>
    using namespace BOOST_SPIRIT_CLASSIC_NS;
    using namespace phoenix;
    
    // actor pour la creation de règles paramétrées par 1 argument:
    template<typename TRetour, typename TLazyRegle, typename TArg>
    struct regle_lazy
    {
       template<class Tuple> struct result {typedef TRetour type;};
       regle_lazy(TLazyRegle P_regle,TArg& P_arg):m_regle(P_regle),m_arg(P_arg)
       {
       }
       TRetour operator()()const
       {// on appele la regle avec l'évaluation de l'argument
          return m_regle(m_arg());
       }
    protected:
       TLazyRegle m_regle;
       TArg& m_arg;
    };
    // méthode pour construire facilement une règle_lazy:
    template<class TRetour, class TRegle, class TArg>
    regle_lazy<TRetour,TRegle,TArg> regle_lazy_p(const TRegle &P_regle, TArg&P_arg)
    {
       return regle_lazy<TRetour, TRegle, TArg>(P_regle,P_arg);
    }
    
    class MaGrammaire
       :public grammar<MaGrammaire>
    {
    public:
       // définition de la structure closure pour les variables associées aux règles:
       struct variable_taille : boost::spirit::closure<variable_taille, size_t>
       {
         member1 NbrElts;
       };
    
       template <typename ScannerT>
       struct definition
       {
    
          template <typename ExactT>
          static fixed_loop_gen <ExactT>
          generer_repeat_p(ExactT const & exact)
          {
            return repeat_p(exact);
          }
    
          // définition de la grammaire:
          definition(MaGrammaire const& self)
          {
             liste             = uint_p[liste.NbrElts=arg1]>>":">>lire_liste;
             lire_liste        = lazy_p( regle_lazy_p<rule<ScannerT> >(
                      phoenix::bind(&fixed_loop_gen<size_t>::operator[]<rule<ScannerT> >)(phoenix::bind(&generer_repeat_p<size_t>)(arg1),var(element))
                      ,liste.NbrElts
                   )
                );
             element           = uint_p>>",";
          }
    
          // définition de la racine:
          rule<ScannerT,typename variable_taille::context_t> const& start() const
             {return liste;}
       protected:
          // les règles:
          rule<ScannerT,typename variable_taille::context_t> liste;
          rule<ScannerT> element;
          rule<ScannerT> lire_liste;
    
       };
    };
    
    #include <iostream>
    int main()
    {
       MaGrammaire MonParseur;
    
       std::string L_strChaine("6:1,2,3,4,5,6,");
       parse_info<char const*> info = parse(
            L_strChaine.c_str(),
            L_strChaine.c_str()+L_strChaine.length(),
            MonParseur
        );
        if (info.full)
            std::cout << "Parse succeeded!\n";
        else
            std::cout << "Parse failed!\n";
       return std::getc(stdin);
    }
    Et là ça passe.
    Mais si je reprend un exemple beaucoup plus simple:
    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
    #include <iostream>
    #include <boost/spirit.hpp>
    #include <boost/spirit/phoenix.hpp>
    using namespace BOOST_SPIRIT_CLASSIC_NS;
    using namespace phoenix;
     
    template<typename A>
    A maFonction(A a)
    {
       return a;
    }
     
    template<typename A, typename B>
    A maFonction(A a, B b)
    {
       return a+A(b);
    }
     
    int main()
    {
       std::cout<<phoenix::bind(&maFonction<int>)(3)()<<std::endl;
       std::cout<<phoenix::bind(&maFonction<int,short>)(3,4)()<<std::endl;
       return std::getc(stdin);
    }
    Ca compile sous visual mais pas sous gcc (error: no matching function for call to `bind(<unknown type>)'). Et là je trouve dommage que gcc n'arrive pas à comprendre le type du paramètre de bind automatiquement. C'est assez gênant si je dois systématiquement lever explicitement l'ambigüité (alors qu'à mon avis, il n'y en a pas!).

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

Discussions similaires

  1. Spirit : nécessité de connaître Phoenix ?
    Par oodini dans le forum Boost
    Réponses: 1
    Dernier message: 08/02/2014, 10h18
  2. boost spirit + boost bind, la galére
    Par Sahengette dans le forum Boost
    Réponses: 8
    Dernier message: 07/07/2012, 13h53
  3. [Spirit] utilisation de phoenix::ref et de bind
    Par niarkyzator dans le forum Boost
    Réponses: 2
    Dernier message: 20/05/2010, 13h06
  4. Spirit + phoenix + closure
    Par 3DArchi dans le forum Boost
    Réponses: 2
    Dernier message: 08/10/2008, 12h59
  5. Bind - sous-domaine
    Par _Gabriel_ dans le forum Réseau
    Réponses: 4
    Dernier message: 07/03/2004, 11h54

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