2014-11-06 3 views
2

Когда я разбираю ввод как std :: string, я получаю строку, но когда я анализирую это как double_, структура fusion содержит некоторое очень небольшое число, а не то, что ожидается.Почему я не могу разобрать этот double_?

#include <boost/spirit/include/qi.hpp> 
#include <boost/fusion/include/adapt_struct.hpp> 

#include <string> 

// http://www.boost.org/doc/libs/1_57_0/libs/spirit/example/qi/employee.cpp 

namespace FormatConverter { 
    namespace qi = boost::spirit::qi; 
    namespace ascii = boost::spirit::ascii; 
    // TODO: should this have an initializer? 
    struct asc { 
     double timestamp; 
    }; 
} 

BOOST_FUSION_ADAPT_STRUCT(
    FormatConverter::asc, 
     (double, timestamp) 
) 

namespace FormatConverter { 

    template <typename Iterator> 
    struct asc_parser : qi::grammar< Iterator, asc(), ascii::space_type > 
    { 
     asc_parser() 
      : asc_parser::base_type(start) { 
       timestamp %= qi::double_ ; 
       start %= timestamp ; 
       ; 
     } 
     qi::rule< Iterator, double, ascii::space_type > timestamp; 
     qi::rule< Iterator, asc(), ascii::space_type > start; 
    }; 
} 

И я пробовал с:

#define BOOST_TEST_MODULE parser 
#include <boost/test/included/unit_test.hpp> 

#include "../FormatConverter/FormatConverter.h" 

#include <string> 

BOOST_AUTO_TEST_SUITE(TestSuite1) 
BOOST_AUTO_TEST_CASE(timestamp) { 
    namespace qi = boost::spirit::qi; 
    namespace ascii = boost::spirit::ascii; 
    using iterator_type = std::string::iterator; 
    using parser_type = FormatConverter::asc_parser<iterator_type>; 

    parser_type grammar; 
    FormatConverter::asc record; 

    std::string str("161.096841 "); 
    auto beg = str.begin(); 
    auto end = str.end(); 

    auto success = qi::phrase_parse(beg, end, grammar, ascii::space, record); 
    BOOST_REQUIRE(success); 
    BOOST_REQUIRE(beg==end); 

    std::cout << "timestamp: " << boost::fusion::as_vector(record) << std::endl; 
} 
BOOST_AUTO_TEST_SUITE_END() 
+0

каждый раз, клянусь, я не могу написать его должным образом. я знаю это, но это всегда так, как я его набираю. – user2240431

ответ

6

Вы пропустили в атрибуте с ():

qi::rule< Iterator, double, ascii::space_type > timestamp; 

должен быть

qi::rule< Iterator, double(), ascii::space_type > timestamp; 

Поскольку порядок PARAMS в qi::rule может быть произвольным (кроме Iterator), внутри lib использует некоторые черты, чтобы распознать, что является attr, который является шкипером, и т. Д. Поле attr должно быть в виде function-sig, то есть synthesized(inherited), если вы напишете double, оно не будет признано attr, поэтому ваше правило timestamp фактически будет иметь unused_type вместо double как его attr, то есть, record.timestamp не будет заполняться парсером, он не инициализирован.

+1

Автор решил поддержать простоту 'T' в дополнение к' T() 'недавно [[1] (https://github.com/boostorg/spirit/ commit/e34a955f2fbbf374870dee3329f89805cd775e6c)], поэтому первый будет работать в будущих выпусках. – Jamboree

+0

Спасибо. Я сделал предположение, что() не потребуется для встроенных типов. Для меня, кажется, нелогично писать double() – user2240431

 Смежные вопросы

  • Нет связанных вопросов^_^