Pregunta

No estoy siendo capaz de averiguar lo que está mal en mi código. plantillas de Boost están haciendo me vuelve loco! No puedo hacer cara o cruz de todo esto, así que sólo tenía que preguntar.

¿Qué hay de malo en esto?

#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';
}

El número de errores es inmensa; Yo sugeriría que las personas que quieren ayudar a la elaboración de este en su sobre (confía en mí, pegando aquí es poco práctico). Estoy usando la última versión TDM-CCG (GCC 4.4.1) e impulsar la versión 1.39.00.

Como beneficio adicional, quisiera pedir a otras dos cosas: si la nueva funcionalidad static_assert de C ++ 0x ayudará a impulsar en este sentido, y si la aplicación que he citado anteriormente es una buena idea, o si debería usar Algoritmos biblioteca de cadenas de impulso. Sería el turismo probablemente dará un rendimiento mucho mejor?

Gracias.

- editar

El siguiente ejemplo muy mínima falla al principio con exactamente el mismo error como el código de seguridad.

#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;
}

- 2 editar

Todavía no sé por qué no funcionó en mi versión antigua de Boost (1,39), pero la actualización a Boost 1,42 resuelto el problema. El código siguiente se compila y se ejecuta a la perfección con 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;
}

Gracias por los consejos, hkaiser.

¿Fue útil?

Solución

Varias observaciones: a) no utilizar la versión beta Espíritu V2 distribuido con V1.39 y V1.40 Boost. Use al menos Espíritu V2.1 (como se presenta con v1.41 Boost) en su lugar, ya que contiene un mucho de correcciones de errores y mejoras de rendimiento (tanto, el tiempo de compilación en tiempo de ejecución y rendimiento). Si no puede cambiar las versiones de Boost, lea aquí de cómo proceder. b) Trate de evitar el uso de boost :: lambda o boost :: bind con el Espíritu V2.x. Sí, lo sé, los docs decir que funciona, pero hay que saber lo que está haciendo. Utilizar expresiones impulso :: phoenix lugar. Espíritu 'sabe' sobre Phoenix, lo que hace que la escritura acciones semánticas más fácil. Si utiliza Phoenix, su código se verá así:

#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] 
        ) 
    ; 

Sin embargo, su programa de análisis global será aún más sencillo si utiliza reglas de propagación de atributos incorporados de Spirit:

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

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

es decir. sin necesidad de tener acciones semánticas en absoluto. Si necesita más información sobre el manejo de atributos, consulte la serie de artículos sobre la magia de atributos en el sitio web del Espíritu.

Editar:

En cuanto a su pregunta static_assert: sí static_assert, puede mejorar los mensajes de error, ya que puede ser usado para disparar los errores de compilación tan pronto como sea posible. De hecho, el Espíritu utiliza esta técnica ampliamente ya. Pero no es posible proteger al usuario de conseguir esos enormes mensajes de error en todos los casos, pero sólo para los errores del usuario al programador esperaba. Sólo conceptos (que por desgracia no lo hacen en el nuevo estándar de C ++) podrían haber sido utilizados para reducir en general teh tamaño de los mensajes de error.

En cuanto a la pregunta de cuerdas Algoritmos de su Boost: desde luego que es posible utilizar esta biblioteca para tareas simples como la suya. Que incluso podría ser mejor usar Boost.Tokenizer (si todo lo que necesita es dividir la cadena de entrada en la ':'). El rendimiento del Espíritu debe ser comparable con el rendimiento correspondiente de los algoritmos de cadena, pero esto ciertamente depende del código que va a escribir. Si se supone que el algoritmo utilizado cadena requerirá un paso sobre los datos de la cadena de entrada, entonces el Espíritu no será más rápido (ya que está haciendo una pasada también).

Ni los algoritmos de Cuerda Boost ni el refuerzo Tokenizer le puede dar la verificación de los caracteres coincidentes. Su Espíritu gramática coincide con sólo los caracteres que ha especificado en las clases de personajes. Así que si usted necesita este juego / verificación, se debe utilizar ya sea alcohol o Boost expresión regular.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top