Question

Je ne suis pas en mesure de comprendre ce qui ne va pas avec mon code. Les modèles de Boost me font devenir fou! Je ne peux pas faire de toutes ces têtes ou queues, donc je viens dû demander.

Quel est le problème avec ça?

#include <iostream>
#include <boost/lambda/lambda.hpp>
#include <boost/spirit/include/qi.hpp>

void parsePathTest(const std::string &path)
{
    namespace lambda = boost::lambda;
    using namespace boost::spirit;

    const std::string permitted = "._\\-#@a-zA-Z0-9";
    const std::string physicalPermitted = permitted + "/\\\\";
    const std::string archivedPermitted = permitted + ":{}";

    std::string physical,archived;

    // avoids non-const reference to rvalue
    std::string::const_iterator begin = path.begin(),end = path.end();

    // splits a string like "some/nice-path/while_checking:permitted#symbols.bin"
    // as physical = "some/nice-path/while_checking"
    // and archived = "permitted#symbols.bin" (if this portion exists)
    // I could barely find out the type for this expression
    auto expr
        =   ( +char_(physicalPermitted) ) [lambda::var(physical) = lambda::_1]
            >> -(
                    ':'
                    >> (
                           +char_(archivedPermitted) [lambda::var(archived) = lambda::_1]
                       )
                )
        ;

    // the error occurs in a template instantiated from here
    qi::parse(begin,end,expr);

    std::cout << physical << '\n' << archived << '\n';
}

Le nombre d'erreurs est immense; Je suggère des gens qui veulent aider à la rédaction de ce sur leur sur (croyez-moi, coller ici est peu pratique). J'utilise la dernière version TDM-GCC (GCC 4.4.1) et la version Boost 1.39.00.

En prime, je voudrais poser une autre deux choses: si les nouvelles fonctionnalités de static_assert de C ++ 0x rehausseront dans ce sens, et si la mise en œuvre que j'ai cité plus haut est une bonne idée, ou si je devrais utiliser bibliothèque cordes algorithmes Boost. ce dernier donnerait probablement une meilleure performance?

Merci.

- modifier

L'exemple suivant de très minime échoue à d'abord avec exactement la même erreur que le code ci-dessus.

#include <iostream>
#include <boost/spirit/include/qi.hpp>

int main()
{
    using namespace boost::spirit;

    std::string str = "sample";
    std::string::const_iterator begin(str.begin()), end(str.end());

    auto expr
        =   ( +char_("a-zA-Z") )
        ;

    // the error occurs in a template instantiated from here
    if (qi::parse(begin,end,expr))
    {
        std::cout << "[+] Parsed!\n";
    }
    else
    {
        std::cout << "[-] Parsing failed.\n";
    }

    return 0;
}

- modifier 2

Je ne sais toujours pas pourquoi il ne fonctionne pas dans mon ancienne version de Boost (1,39), mais la mise à niveau pour stimuler 1,42 résolu le problème. Le code suivant compile et fonctionne parfaitement avec Boost 1,42:

#include <iostream>
#include <boost/spirit/include/qi.hpp>

int main()
{
    using namespace boost::spirit;

    std::string str = "sample";
    std::string::const_iterator begin(str.begin()), end(str.end());

    auto expr
        =   ( +qi::char_("a-zA-Z") ) // notice this line; char_ is not part of 
                                     // boost::spirit anymore (or maybe I didn't 
                                     // include the right headers, but, regardless, 
                                     // khaiser said I should use qi::char_, so here 
                                     // it goes)
        ;

    // the error occurs in a template instantiated from here
    if (qi::parse(begin,end,expr))
    {
        std::cout << "[+] Parsed!\n";
    }
    else
    {
        std::cout << "[-] Parsing failed.\n";
    }

    return 0;
}

Merci pour les conseils, hkaiser.

Était-ce utile?

La solution

Plusieurs remarques: a) ne pas utiliser l'Esprit V2 version bêta distribuée avec Boost V1.39 et V1.40. Utilisez au moins Esprit V2.1 (comme sorti avec v1.41 Boost) à la place, car il contient un beaucoup de corrections de bugs et des améliorations de performance (à la fois, le temps de compilation et de la performance d'exécution). Si vous ne pouvez pas passer d'une version de Boost, lisez ici pour savoir comment procéder. b) Essayez d'éviter d'utiliser boost :: lambda ou boost :: bind avec l'Esprit v2.x. Oui, je sais, les docs dire que cela fonctionne, mais vous devez savoir ce que vous faites. Utilisez boost :: expressions de Phoenix à la place. Esprit « sait » à propos de Phoenix, ce qui rend l'écriture des actions sémantiques plus facile. Si vous utilisez Phoenix, votre code ressemblera à:

#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>

namespace qi = boost::spirit::qi;
namespace phoenix = boost::phoenix;

std::string physical, archived;  
auto expr 
    =   ( +char_(physicalPermitted) ) [phoenix::ref(physical) = qi::_1] 
    >> -( 
            ':' 
            >> ( +char_(archivedPermitted) )[phoenix::ref(archived) = qi::_1] 
        ) 
    ; 

Mais votre analyseur global sera encore plus simple si vous utilisez les règles de propagation d'attributs intégrés de l'Esprit:

std::string physical;
boost::optional<std::string> archived;  

qi::parse(begin, end, 
    +qi::char_(physicalPermitted) >> -(':' >> +qi::char_(archivedPermitted)),
    physical, archived);

i.e.. pas besoin d'avoir des actions sémantiques du tout. Si vous avez besoin de plus d'informations sur la gestion des attributs, voir la série d'articles au sujet de la magie des attributs sur le site Web de l'Esprit.

Edit:

En ce qui concerne votre question static_assert: oui static_assert, peut améliorer les messages d'erreur car il peut être utilisé pour déclencher des erreurs du compilateur le plus tôt possible. En fait, l'Esprit utilise cette technique largement déjà. Mais il est impossible de protéger l'utilisateur d'obtenir ces énormes messages d'erreur dans tous les cas, mais seulement pour les erreurs de l'utilisateur le programmeur ne s'y attendait. Seuls les concepts (qui, malheureusement, ne sont pas passées dans la nouvelle norme C ++) auraient pu être utilisés pour réduire généralement Teh taille des messages d'erreur.

En ce qui concerne votre question Boost chaîne algorithmes: certainement il est possible d'utiliser cette bibliothèque pour des tâches simples comme la vôtre. Vous pourriez même être préférable d'utiliser Boost.Tokenizer (si vous avez besoin est de diviser la chaîne d'entrée à la « : »). La performance de l'Esprit devrait être comparable à la performance correspondante des algorithmes de chaîne, mais cela dépend certainement du code que vous allez écrire. Si vous supposez que l'algorithme de chaîne utilisé nécessite un passage sur les données de la chaîne d'entrée, alors Esprit ne sera pas plus rapide (comme il est fait une passe aussi bien).

Ni les algorithmes de chaîne Boost ni le Boost Tokenizer peut vous donner la vérification des caractères correspondants. Votre grammaire Esprit correspond uniquement les caractères que vous avez spécifié dans les classes de personnages. Donc, si vous avez besoin de cette mise en correspondance / vérification, vous devez utiliser soit Esprit ou Boost Regex.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top