Почему я не могу разобрать это double_?

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

#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()

1 ответ

Решение

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

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

должно быть

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

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

Другие вопросы по тегам