2016-12-30 61 views
3

運行以下代碼會導致崩潰。爲什麼?boost :: spirit :: multi_pass帶謂詞和替代的崩潰

#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

您是否試圖可靠地解析雙打和整數?搜索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,至少不能用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; 
}