2016-12-30 3 views
3

Выполнение следующего кода приводит к сбою. Зачем?boost :: spirit :: multi_pass crash с предикатом и альтернативой

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

using namespace boost::spirit; 
typedef multi_pass< 
      std::string::const_iterator, 
      iterator_policies::default_policy< 
       iterator_policies::first_owner, 
       iterator_policies::no_check, 
       iterator_policies::buffering_input_iterator, 
       iterator_policies::split_std_deque>> 
     string_mp_iterator; 

int main() { 
    std::string input = "234"; 
    string_mp_iterator input_begin(input.begin()), 
      input_end((string_mp_iterator())); 
    qi::rule<string_mp_iterator, boost::variant<int, double>()> r = 
      &qi::lit('1') >> qi::int_ | qi::double_; 
    qi::parse(input_begin, input_end, r); 
    return 0; 
} 

Чтобы воспроизвести аварии, я, кажется, нужно иметь как предикат и последующую альтернативу, чтобы с помощью multi_pass итератора, а для ввода не удовлетворяет предикат.

У меня такое ощущение, что я как-то неправильно использовал multi_pass, но я не понимаю, в чем проблема.

+2

Вы пытаетесь разобрать удвоение против ints надежно? Поиск https://stackoverflow.com/search?q=strict_real_policies – sehe

+0

Нет, это просто пример, где я стараюсь, чтобы вещи были максимально простыми. Тем не менее это будет полезно в других местах. Благодаря! –

+0

Это характер неопределенного поведения: вы не можете рассуждать об этом, потому что результаты не определены – sehe

ответ

2

Просто исправить инициализатор для конечного итератора.

string_mp_iterator input_end(input.end()); 

Поскольку это не итератор ввода, вы не можете использовать построенный по умолчанию итератор по умолчанию.

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

using namespace boost::spirit; 
typedef multi_pass< 
    std::string::const_iterator, 
    iterator_policies::default_policy< 
     iterator_policies::first_owner, iterator_policies::no_check, 
     iterator_policies::buffering_input_iterator, 
     iterator_policies::split_std_deque>> 
    string_mp_iterator; 

int main() { 
    std::string input = "234"; 
    string_mp_iterator input_begin(input.begin()), 
         input_end(input.end()); 
    qi::rule<string_mp_iterator, boost::variant<int, double>()> r = &qi::lit('1') >> qi::int_ | qi::double_; 
    qi::parse(input_begin, input_end, r); 
} 
+0

Это явно исправляет код, но мне все же остается загадкой, почему предикат и альтернативная комбинация необходимы, чтобы вызвать сбой. В моем реальном использовании я не переношу итератор строки в 'multi_pass'. Тем не менее, это подтверждает мое подозрение, что мое использование 'multi_pass' неверно. –

2

Кажется, вы не можете обернуть std :: string с помощью итератора multi_pass, по крайней мере, не с iterator_policies::buffering_input_iterator std :: string имеет указатель на основе end, а не null. Вот почему итератор появляется несовместимо. Если вы собираетесь просто разобрать std::string, используйте итераторы напрямую, поскольку они отвечают требованию multi_pass. Если вы планируете изменить в поток (code sorta from here):

typedef std::istreambuf_iterator<char> base_iterator_type; 
typedef boost::spirit::multi_pass<base_iterator_type> forward_iterator_type; 

main() 
{ 
    std::istringstream input("234"); 

    base_iterator_type in_begin(input); 
    base_iterator_type in_end; 
    forward_iterator_type fwd_begin = boost::spirit::make_default_multi_pass(in_begin); 
    forward_iterator_type fwd_end = boost::spirit::make_default_multi_pass(in_end); 

    qi::rule<forward_iterator_type, boost::variant<int, double>()> r = 
     &qi::lit('1') >> qi::int_ | qi::double_; 
    qi::parse(fwd_begin, fwd_end, r); 
    return 0; 
} 

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

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