使用提升精神表达

Using boost spirit expression

我的boost spirit有问题expression.The原代码比较复杂,我做了一个小快照。 这段代码在调试模式下按预期工作,在发布时没有,解析 returns false,但应该 return true(我在 Visual Studio 2019 测试它)

int main() {
    namespace qi = boost::spirit::qi;

    auto X19 = qi::lit("                   ") | qi::lit(" 0.000000000000D+00");
    auto i4 = qi::uint_;
    string str = "1234                   1234";
    auto f = str.cbegin();
    auto l = str.cend();
    bool ret = qi::parse(f, l, ( i4 >> X19 >> i4 ));
}

下一个快照适用于两种模式:

int main() {
    namespace qi = boost::spirit::qi;

    auto i4 = qi::uint_;
    string str = "1234                   1234";
    auto f = str.cbegin();
    auto l = str.cend();
    bool ret = qi::parse(f, l, ( i4 >> (qi::lit("                   ") | qi::lit(" 0.000000000000D+00")) >> i4 ));
    cout << ret << endl;
    return ret;
}

我做错了什么,这样划分长表达式? 谢谢

你运行 一头扎进了带有 Spirit 的 Proto 表达式的悬空临时陷阱。简短规则是:

Don't use auto with Spirit expressions

您的程序展示了 Undefined Behaviour: see it Live On Compiler Explorer


解决方法涉及 BOOST_SPIRIT_AUTOqi::copy(在最近的提升版本之前仅作为 boost::proto::deep_copy 可用)。

固定

Live On Coliru

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

int main() {
    namespace qi = boost::spirit::qi;

    auto i4 = qi::copy(qi::uint_);
    auto X19 = qi::copy(               //
          qi::lit("                   ") //
        | qi::lit(" 0.000000000000D+00")//
        );

    std::string str = "1234                   1234";
    auto        f = str.cbegin(), l = str.cend();

    bool ret = qi::parse(f, l, (i4 >> X19 >> i4));
    std::cout << std::boolalpha << ret << "\n";
}

版画

true

奖金

  1. 请注意,Spirit X3 不再具有此 restriction/problem:Live On Coliru

    #include <boost/spirit/home/x3.hpp>
    
    int main() {
        namespace x3 = boost::spirit::x3;
    
        auto i4 = x3::uint_;
        auto X19 =                           //
            x3::lit("                   ")   //
            | x3::lit(" 0.000000000000D+00") //
            ;
    
        std::string str = "1234                   1234";
        auto        f = str.cbegin(), l = str.cend();
    
        bool ret = parse(f, l, (i4 >> X19 >> i4));
        std::cout << std::boolalpha << ret << "\n";
    }
    
  2. 你可能真的想要

    qi::uint_parser<int, 10, 4, 4> i4;
    // or
    x3::uint_parser<int, 10, 4, 4> i4;
    
  3. 看起来很像是在解析类似 COBOL 的(固定宽度)记录,在这种情况下,我认为有更好的方法来组织语法以使其可靠。